我有一个基于Spring的java应用程序,其中包含一些有用的组件。作为系统的一部分,我有一个groovy脚本,来处理一些报告。我想从groovy脚本中调用spring组件。
当我用Java编写时,我需要在@Autowired
内使用@Component
注释,即
@Component
class Reporter{
@Autowired
SearchService searchService;
void report(){
searchService.search(...);
...
}
}
我如何从groovy做同样的事情?
首先,我如何为整个脚本定义@Component
?
以下代码:
@Component class Holder{
@Autowired
SearchService searchService;
def run(){
searchService.search("test");
}
}
new Holder().run()
在searchService
上的NPE失败。
如果重要的话,我正在使用Java GroovyClassloader
运行groovyscripts。
非常感谢提前!
答案 0 :(得分:4)
如果您使用@Component
,则应将Spring上下文创建为:
def ctx = new GenericApplicationContext()
new ClassPathBeanDefinitionScanner(ctx).scan('') // scan root package for components
ctx.refresh()
或在XML中:
<context:component-scan base-package="org.example"/>
如果上面创建了上下文,您的代码应该有效。以下是Groovy Codehaus
的示例import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
@Component class CalcImpl3 {
@Autowired private AdderImpl adder
def doAdd(x, y) { adder.add(x, y) }
}
答案 1 :(得分:1)
三种可能性:
如果您的Groovy代码可以预编译并包含在类路径中,那么它将在<context:component-scan>
期间创建并注入任何其他bean。听起来可能并非如此,因为您使用的是GroovyClassLoader
。
使用Spring Dynamic Language Support并使用<lang:groovy>
创建bean,而不是使用GroovyClassLoader
。然后使用<lang:property>
注入您的属性,而不是使用@Autowired
。
如果您仍然需要使用GroovyClassLoader
,那么您可以使用AutowiredAnnotationBeanPostProcessor
来请求注入bean。
例如,如果obj
是对GroovyClassLoader
创建的对象的引用:
AutowiredAnnotationBeanPostProcessor aabpp =
(AutowiredAnnotationBeanPostProcessor)applicationContext.
getBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
aabpp.processInjection(obj);
还有第四种可能性,但我不确定它是否适用于GroovyClassLoader
,即使用Load-time Weaving。