使用Groovy配置中的Spring动态语言支持 [英] Using Spring Dynamic Languages Support from Groovy Configuration
问题描述
我想使用动态语言支持,以从Groovy脚本创建可重载 bean(在运行时 )。我想避免 xml
配置,并在 Spring Boot
应用程序上下文中使用注释(或类似的)。
这是对问题已经被问到,扩展名是我想用 我已经快速浏览了javadoc的 ScriptFactoryPostProcessor ,并提出了工作示例。我想知道为什么 beans.xml - 有效! (但我想在 Application.groovy 中定义bean,而不是 Application.groovy v1) - 有效! (但是是一个非常丑陋的解决方法) Application.groovy(v2) - 无效 - 为什么不能? 看起来像是s与bean的定义在ApplicationContext的生命周期中的初始化方式/方式有关。我试过使用 相关: BeanPostProcessors
, Handlers
, Parsers
,无论如何。
Application.groovy(v2)
不起作用?
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>
$ 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()
}
}
@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)
}
}
@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对其进行注释
- 在mybeans.xml中使用lang命名空间 / li>
$ b $ 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屋!