我想使用Spring Framework的Dynamic Languages Support。
在XML中,我只使用lang
命名空间,但我想使用Java配置(即@Configuration
类)仅。< / p>
我可以想象我可以通过从org.springframework.scripting.config
package,inc初始化所有地狱来做到这一点。他们创建的所有BeanPostProcessor
,Handler
,Parser
和FactoryBean
,但我真的不想去那里。
还有其他方法吗?如果没有,那么从Groovy脚本创建可重新加载的bean所需的最小配置是什么?
答案 0 :(得分:7)
您为什么不直接通过电子邮件询问我们? : - )
我看到XML Lang的支持非常神奇。有足够的内容基于BeanDefinition
及其attributes
。另外,ProxyFactory
有一些CGLIB
和lang:property
的钩子。
我在JavaConfig中看到的是来自Spring Integration的ScriptEvaluator
和RefreshableResourceScriptSource
的一些Java类包装器:
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class RefreshableScriptJavaConfigTests {
@Autowired
private Calculator calculator;
@Test
public void testGroovyRefreshableCalculator() {
assertEquals(5, this.calculator.add(2, 3));
}
@Configuration
public static class ContextConfiguration {
@Value("classpath:org/springframework/integration/scripting/config/jsr223/Calculator.groovy")
private Resource groovyScriptResource;
@Bean
public ScriptEvaluator groovyScriptEvaluator() {
return new GroovyScriptEvaluator();
}
@Bean
public Calculator calculator() {
return new Calculator(new RefreshableResourceScriptSource(this.groovyScriptResource, 1000));
}
}
public static class Calculator {
private final ScriptSource scriptSource;
@Autowired
private ScriptEvaluator scriptEvaluator;
public Calculator(ScriptSource scriptSource) {
this.scriptSource = scriptSource;
}
public int add(int x, int y) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("x", x);
params.put("y", y);
return (int) this.scriptEvaluator.evaluate(this.scriptSource, params);
}
}
}
Calculator.groovy
的位置:
x + y
我知道它不像从XML定义的接口和配置看起来那么灵活,但至少它会帮助你看到我们的位置。
随意提出有关此问题的JIRA问题,我们将看到我们可以在这里做些什么。类似于@EnableScripting
@ScriptSource(refreshDelay = 1000)
方法的Resource
和@Bean
。
我认为现在您只需@Import
一些带有lang
定义的XML代码段。
干杯, 阿尔乔姆
答案 1 :(得分:2)
我正在进行down the same path(正在进行中),并且已经设法通过在准备Spring应用程序时添加bean定义来初始化可重新加载的Groovy脚本。在我的示例中,我使用spring-boot
。
如果添加以下AddBeanDefinitionsListener
侦听器类和ScriptFactoryPostProcessor
bean,则可以轻松地初始化Groovy脚本...
<强> AddBeanDefinitionsListener.groovy 强>
public class AddBeanDefinitionsListener
implements ApplicationListener<ApplicationPreparedEvent> {
Map<String, BeanDefinition> beanDefs
AddBeanDefinitionsListener(Map<String, BeanDefinition> beanDefs) {
this.beanDefs = beanDefs
}
@Override
void onApplicationEvent(ApplicationPreparedEvent event) {
def registry = (BeanDefinitionRegistry) event.applicationContext
.autowireCapableBeanFactory
beanDefs.each { String beanName, BeanDefinition beanDef ->
registry.registerBeanDefinition(beanName, beanDef)
}
}
/* Static Utility methods */
static BeanDefinition groovyScriptFactory(String scriptLocation) {
def bd = BeanDefinitionBuilder.genericBeanDefinition(GroovyScriptFactory)
.addConstructorArgValue(scriptLocation)
.getBeanDefinition()
bd.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 1000)
bd
}
}
<强> Application.groovy 强>
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application)
app.addListeners(new AddBeanDefinitionsListener([
'foobar0': groovyScriptFactory("file:/some/path/Foobar0Service.groovy"),
'foobar1': groovyScriptFactory("file:/some/path/Foobar1Service.groovy")
]))
app.run(args)
}
@Bean
ScriptFactoryPostProcessor scriptFactory() {
new ScriptFactoryPostProcessor()
}
}
(如果用Spring 4.2's events实施,可能会更好吗?)