2017-04-05 5 views
1

Spring 4.2 이상에서는 @EventListener annotation을 "condition"표현식과 함께 사용할 수있다.Spring 4.2+ : @EventListener 조건 표현식 내에서 Spring 빈 인스턴스를 참조하는 방법

제 시나리오에서는 이벤트 객체의 id를 .properties 파일에 구성된 일반 표현식과 일치시켜야합니다.

그러나 루트 컨텍스트는 이벤트 객체 자체 인 것처럼 보이지만 조건의 정규 표현식에서 모든 bean의 속성이나 메소드를 참조하는 것은 불가능한 것처럼 보입니다.

지금까지 클래스 이름을 기반으로 이벤트 ID 패턴 속성을 설정하는 추상 클래스가 있습니다. 목표는 각 이벤트 리스너의 구현을 가능한 깨끗하고 단순하게 만드는 것입니다.

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()); 
    } 
} 

문제는 표현이다를

@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; 
    } 
} 

특성 파일은 다음과 같습니다

"# event.eventid @regExpEventHandler "는 @EventListener에 의해 사용되는 컨텍스트에서 찾을 수 없습니다 regExpEventHandler.getEventIdPattern @ 일치()"빈이 때문에

은 작동하지 않습니다. "

여기에 기존 스프링 빈의 메소드 또는 속성에 액세스 할 수있는 방법이 있습니까? 이 시나리오에 대한 다른 더 나은 접근법은 무엇입니까?

은 내가 쉽게 같은 것을 사용하여 정적 상수 또는 메서드에 액세스 할 수 있습니다 알고

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

그러나 @Value 표현을 사용하여 특성 파일에서 초기화 할 수 없습니다 문자열 상수 (최종 정적)을.

작업 할 수 NON-FINAL 정적 상수를 사용하지만 이벤트 리스너는 우리가 피하고자하는 @Value 표현을 사용하여 비 정적 변수에서 정적 상수를 초기화하는 보일러 플레이트를 추가해야 .

미리 감사드립니다.

+0

왜'regExpEventHandler'가 bean이 될까요? 그것은 bean이 아닌 속성입니다 ... –

+0

만약 내가 따라갈 지 모르겠지만 ... 제 이해는 Spring EL 표현식 안에서 콩을 @를 사용하여 참조 할 수 있다는 것입니다. 나는 또한 # event.eventid와 같은 좀 더 간단한 것을 시도했다. $ {regExpEventHandler}는 프라퍼티 파일에서 상응하는 값을 얻어야 만한다.하지만 표현식도 실패한다. –

+0

네, 그렇긴하지만 당신은 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로 전환 한 후 완벽하게 작동합니다 ... 많은 감사드립니다! –