Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

322
Visualizações
Spring 4.2+ : How to reference a Spring bean instance from inside an @EventListener condition expression

In Spring 4.2+, we can use @EventListener annotation with a "condition" expression.

In my scenario, I need to match the id of the event object with a regular expression that is configured in a .properties file.

However, it seems impossible to reference any bean's property or method from the condition's regular expression, as the root context seems to be the event object itself.

So far, I have an abstract class, that sets the event id pattern property based on the class name. The goal is to make the implementation of each Event Listener as clean and simple as possible.

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

The properties file looks like this:

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

And then, I have a sample Event Listener that extends the above Abstract class:

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

The problem is that the expression

"#event.eventid matches @regExpEventHandler.getEventIdPattern()"

does not work, because the bean "@regExpEventHandler" cannot be found in the context used by the @EventListener.

Is there a way to access methods or properties of an existing Spring Bean here? Any other better approach for this scenario ?

I know I can easily access STATIC constants or methods by using something like:

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

But a String constant (static final) cannot be initialized from a properties file using a @Value expression.

Using NON-FINAL static constants can work, but then EACH Event Listener needs to add boiler-plate to initialize the static constant from a non-static variable using a @Value expression, which we want to avoid.

Thanks a lot in advance !

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

It works for me - I looked at the EventExpressionEvaluator and saw that it added a bean resolver to the evaluation context...

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

So I wrote a quick test...

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

}

and it works just fine...

bar:org.springframework.context.PayloadApplicationEvent[...
handler:foo

(This was with 4.3.7; boot 1.5.2).

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda