2017-04-05 480 views
1

在Spring 4.2+中,我們可以使用帶有「條件」表達式的@EventListener註釋。Spring 4.2+:如何在@EventListener條件表達式中引用Spring bean實例

在我的方案中,我需要將事件對象的id與在.properties文件中配置的正則表達式匹配。

但是,從條件的正則表達式引用任何bean的屬性或方法似乎是不可能的,因爲根上下文似乎是事件對象本身。

到目前爲止,我有一個抽象類,它根據類名設置事件ID模式屬性。目標是儘可能簡化每個事件監聽器的實現。

@Service 
@PropertySource(value = "classpath:subscriberEventMapping.properties") 
public abstract class AbstractEventHandler implements IEventHandler { 

    private String eventIdPattern; 

    @Autowired 
    Environment env; 

    @Autowired(required = true) 
    public void configureEventIdPattern() { 
     String simpleClassName = this.getClass().getSimpleName(); 
     String resolvedEventIdPattern = env.getProperty(
      simpleClassName.substring(0,1).toLowerCase() + 
      simpleClassName.substring(1, simpleClassName.length())); 
     this.eventIdPattern = resolvedEventIdPattern == null ? ".*" : resolvedEventIdPattern; 
    } 

    public String getEventIdPattern() { 
     return eventIdPattern; 
    } 
} 

屬性文件看起來是這樣的:

regExpEventHandler=^(901|909|998|1000)$ 
dummyEventHandler=^([1-9][0-9]{0,2}|1000)$ 

然後,我有一個擴展上面抽象類樣本事件監聽器:

@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比賽@ regExpEventHandler.getEventIdPattern()」

不起作用,因爲豆‘@regExpEventHandler’不能由@EventListener使用的上下文中找到。

有沒有辦法在這裏訪問現有的Spring Bean的方法或屬性?這種情況下的其他更好的方法?

我知道我可以很容易地通過使用類似訪問靜態常量或方法:

#event.eventid matches T(my.package.RegExpEventHandler.MY_CONSTANT) 

字符串常量(靜態最終)不能從屬性初始化文件中使用@Value表達。

使用非最終靜態常量可以正常工作,但隨後EACH事件監聽器需要增加鍋爐板使用@Value表達,這是我們要避免初始化從非靜態變量靜態常量。

非常感謝!

+0

爲什麼'regExpEventHandler'是一個bean?它是一個屬性不是豆... –

+0

不知道我是否遵循...我的理解是,在Spring EL表達式中,可以使用@引用bean。我也嘗試了一些簡單的事情,例如#event.eventid匹配$ {regExpEventHandler},它應該從屬性文件中獲取相應的值,但表達式也失敗 –

+0

是bean,但您試圖將屬性引用爲bean,去工作。 –

回答

3

它爲我 - 我看着EventExpressionEvaluator並認爲這增加了豆解析器來評估背景下...

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引導)。

+0

非常感謝Gary的幫助......我們使用的是Spring 4.2.6,而我剛剛在這個版本中發現,EventExpressionEvaluator沒有bean解析器......因此我的頭痛......我非常確定切換到4.3.7可能只是解決問題...再次感謝! –

+0

是的 - 它[在4.3中添加](https://jira.spring.io/browse/SPR-13814)。 –

+0

切換到4.3.7後工作完美...非常感謝! –