使用Groovy配置中的Spring动态语言支持 [英] Using Spring Dynamic Languages Support from Groovy Configuration

查看:200
本文介绍了使用Groovy配置中的Spring动态语言支持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用动态语言支持,以从Groovy脚本创建可重载 bean(在运行时 )。我想避免 xml 配置,并在 Spring Boot 应用程序上下文中使用注释(或类似的)。



这是对问题已经被问到,扩展名是我想用 BeanPostProcessors Handlers Parsers 无论如何。

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




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

 < bean class =org.springframework.scripting.support.ScriptFactoryPostProcessor> 
< property name =defaultRefreshCheckDelayvalue =1000/>
< / bean>

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






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


$ b

@SpringBootApplication
public class Application {
public static void main(String [] args){
SpringApplication app = new SpringApplication(Application)
//在编写应用程序之后添加GroovyScriptFactory ...
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()
b.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE ,1000)
registry.registerBeanDefinition('foobar0',bd)
}
})
app.run(args)
}
@Bean
ScriptFactoryPostProcessor scriptFactory() {
新的ScriptFactoryPostProcessor()
}
}






Application.groovy(v2) - 无效 - 为什么不能?

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

看起来像是s与bean的定义在ApplicationContext的生命周期中的初始化方式/方式有关。我试过使用 @Order @DependsOn 来控制bean排序 - 无济于事。值得一提的是,我现在正在重复以下日志 - 看起来像 ScriptFactoryPostProcessor 不断用bean的null定义覆盖bean(为什么?)。

2015-08-27 12:04:11.312信息5780 --- [main] osbfsDefaultListableBeanFactory:
重写bean'scriptFactory.foobar0'的bean定义:替换[Generic bean:class [null];
scope =;抽象= FALSE; lazyInit = FALSE; autowireMode = 0; dependencyCheck = 0; autowireCandidate = TRUE; p
rimary = false; factoryBeanName = NULL; factoryMethodName = NULL; initMethodName = NULL; destroyMethodName = n
ull]与[Generic bean:class [null];范围=;抽象= FALSE; lazyInit = FALSE; autowireMode = 0;依赖
dencyCheck = 0; autowireCandidate = TRUE;初级= FALSE; factoryBeanName = NULL; factoryMethodName = NULL; i
nitMethodName = null;

相关:


解决方案

更简单的选择:




  • 将FooBarService放在类路径中并使用@Component对其进行注释





  • $ b $ li
  • 在mybeans.xml中使用lang命名空间 / li>


-

 < lang :常规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)
}
}


I'd like to use Dynamic Languages Support of Spring Framework, to create a reloadable bean (at runtime!) from a Groovy script. I want to avoid xml configuration, and use annotations (or similar) within a Spring Boot Application context.

This is an extension to a question that's already been asked, the extension being that I DO want to get my hands dirty with BeanPostProcessors, Handlers, Parsers, whatever it takes.

I've had a quick look at the javadoc for ScriptFactoryPostProcessor, and have come up with working examples. I want to know why Application.groovy (v2) doesn't work?


beans.xml - works! (but I want to define the beans in Application.groovy instead of 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) - works! (but is a very ugly workaround)

@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) - doesn't work - why not?

@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")
    }
}

It looks like it's something to do with how/when the beans definitions are initialised in the the lifecycle of an ApplicationContext. I've tried using @Order and @DependsOn to control bean ordering - to no avail. Worth mentioning, I'm now getting the following log repeated - which looks like the ScriptFactoryPostProcessor is continually overwriting the bean with a "null" bean definition (why?).

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]

Related:

  • SPR-10253 - Refreshing annotated Groovy controllers cause ClassCastException
  • SPR-10689 - tag in version 2.5 and higher doesn't work for refreshable Spring MVC endpoints
  • SPR-12300 - Add support for dynamic languages refreshable beans in @Configuration classes

解决方案

Simpler alternatives:

  • put FooBarService on the classpath and annotate it with @Component

or

  • use the lang namespace in mybeans.xml

-

<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)
    }
}

这篇关于使用Groovy配置中的Spring动态语言支持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆