在Spring 4.2+中,我们可以使用带有“条件”表达式的@EventListener注释。
在我的场景中,我需要将事件对象的id与在.properties文件中配置的正则表达式进行匹配。
但是,似乎不可能从条件的正则表达式引用任何bean的属性或方法,因为根上下文似乎是事件对象本身。
到目前为止,我有一个抽象类,它根据类名设置事件id模式属性。目标是使每个事件监听器的实现尽可能简洁明了。
@Service
public class RegExpEventHandler extends AbstractEventHandler {
@Log
private ILog logger;
@Override
@EventListener(condition = "#event.eventid matches @regExpEventHandler.getEventIdPattern()")
public void onEvent(Event event) {
logger.debug("RegExpEventHandler processing : {} with event pattern : {}", event, getEventIdPattern());
}
}
属性文件如下所示:
#event.eventid matches T(my.package.RegExpEventHandler.MY_CONSTANT)
然后,我有一个示例事件监听器,它扩展了上面的Abstract类:
var resultStr = "[{\"Intent\":\"what is manufacturer name?\",\"Entity\":\"Name\",\"Response\":\"Test\",\"Status\":\"0\",\"Created_Date\":\"2017-04-04T00:00:00\",\"Response_Count\":0,\"Response_Count_string\":0},{\"Intent\":\"hi\",\"Entity\":\"hi\",\"Response\":\"hiiii\",\"Status\":\"0\",\"Created_Date\":\"2017-03-28T10:22:00\",\"Response_Count\":0,\"Response_Count_string\":0},{\"Intent\":\"how are you?\",\"Entity\":\"are you fine\",\"Response\":\"good!cool\",\"Status\":\"1\",\"Created_Date\":\"2017-03-28T10:22:38\",\"Response_Count\":0,\"Response_Count_string\":0}]";
result = JSON.parse(resultStr);
var data = result[0].Intent;
问题在于表达式
“#event.eventid匹配@ regExpEventHandler.getEventIdPattern()”
不起作用,因为在@EventListener使用的上下文中找不到bean“@regExpEventHandler”。
有没有办法在这里访问现有Spring Bean的方法或属性?对于这种情况,还有其他更好的方法吗?
我知道我可以使用类似的东西轻松访问STATIC常量或方法:
{{1}}
但是无法使用@Value表达式从属性文件初始化 String constant (static final)。
使用 NON-FINAL 静态常量可以工作,但是 EACH 事件监听器需要添加样板来使用非静态变量初始化静态常量@Value表达式,我们要避免。
提前多多感谢!
答案 0 :(得分:3)
它对我有用 - 我查看了EventExpressionEvaluator
并看到它在评估上下文中添加了一个bean解析器......
public EvaluationContext createEvaluationContext(ApplicationEvent event, Class<?> targetClass,
Method method, Object[] args, BeanFactory beanFactory) {
Method targetMethod = getTargetMethod(targetClass, method);
EventExpressionRootObject root = new EventExpressionRootObject(event, args);
MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(
root, targetMethod, args, getParameterNameDiscoverer());
if (beanFactory != null) {
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
return evaluationContext;
}
所以我写了一个快速测试...
@SpringBootApplication
public class So43225913Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So43225913Application.class, args);
context.publishEvent("foo");
}
@EventListener(condition = "@bar.accept(event)")
public void listen(Object event) {
System.out.println("handler:" + event);
}
@Bean
public Bar bar() {
return new Bar();
}
public static class Bar {
public boolean accept(Object o) {
System.out.println("bar:" + o);
return true;
}
}
}
它运作得很好......
bar:org.springframework.context.PayloadApplicationEvent[...
handler:foo
(这是4.3.7;启动1.5.2)。