java – 使用Groovy配置中的Spring动态语言支持

我想使用Dynamic Languages Support的Spring Framework,从Groovy脚本创建一个可重新加载的bean(在运行时!).我想避免xml配置,并在Spring Boot Application上下文中使用注释(或类似).

这是对question that’s already been asked的扩展,扩展是因为我想用BeanPostProcessors,Handlers,Parsers,无论如何都要弄脏.

我已经快速浏览了ScriptFactoryPostProcessor的javadoc,并提出了一些工作示例.我想知道为什么Application.groovy(v2)不起作用?

beans.xml – 有效! (但我想在Application.groovy中定义bean而不是xml …)

<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor">
    <property name="defaultRefreshCheckDelay" value="1000" />
</bean>

<bean id="foobar0" class="org.springframework.scripting.groovy.GroovyScriptFactory">
    <constructor-arg value="file:/C:/someDir/src/main/static/FoobarService.groovy"/>
</bean>

Application.groovy(v1) – 有效! (但这是一个非常丑陋的解决方法)

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application)
        // Add GroovyScriptFactory after Application is prepared...
        app.addListeners(new ApplicationListener<ApplicationPreparedEvent>() {
            void onApplicationEvent(ApplicationPreparedEvent event) {
                def registry = (BeanDefinitionRegistry) event.applicationContext.autowireCapableBeanFactory
                def bd = BeanDefinitionBuilder.genericBeanDefinition(GroovyScriptFactory)
                        .addConstructorArgValue("file:/C:/someDir/src/main/static/FoobarService.groovy")
                        .getBeanDefinition()
                bd.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 1000)
                registry.registerBeanDefinition('foobar0', bd)
            }
        })
        app.run(args)
    }
    @Bean
    ScriptFactoryPostProcessor scriptFactory() {
        new ScriptFactoryPostProcessor()
    }
}

Application.groovy(v2) – 不起作用 – 为什么不呢?

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application, args)
    }
    @Bean
    ScriptFactoryPostProcessor scriptFactory() {
        new ScriptFactoryPostProcessor()
    }
    @Bean
    GroovyScriptFactory foobar0() {
        new GroovyScriptFactory("file:/C:/someDir/src/main/static/FoobarService.groovy")
    }
}

看起来它与在ApplicationContext的生命周期中初始化bean定义的方式/时间有关.我尝试使用@Order和@DependsOn来控制bean的排序 – 无济于事.值得一提的是,我现在重复了以下日志 – 看起来ScriptFactoryPostProcessor不断用“null”bean定义覆盖bean(为什么?).

2015-08-27 12:04:11.312  INFO 5780 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     :
Overriding bean definition for bean 'scriptFactory.foobar0': replacing [Generic bean: class [null];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; p
rimary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=n
ull] with [Generic bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=0; depen
dencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; i
nitMethodName=null; destroyMethodName=null]

有关:

> SPR-10253 – 刷新带注释的Groovy控制器会导致ClassCastException
> SPR-10689 – 版本2.5及更高版本中的标记不适用于可刷新的Spring MVC端点
> SPR-12300 – 在@Configuration类中添加对动态语言可刷新bean的支持

最佳答案
更简单的替代品:

>将FooBarService放在类路径上并使用@Component注释它

要么

>在mybeans.xml中使用lang命名空间

<lang:groovy id="foobarService"
    script-source="file:src/main/static/FoobarService.groovy" />

Application.groovy

@SpringBootApplication
@ImportResource("classpath:mybeans.xml")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application, args)
    }
}

转载注明原文:java – 使用Groovy配置中的Spring动态语言支持 - 代码日志