Search code examples
javaspringspring-annotations

Spring - applicationContext getBeansWithAnnotation method returns an empty list


My question is about getBeansWithAnnotation method.

I have a custom annotation named MyCustomAnnotation.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@Scope("prototype")
public @interface MyCustomAnnotation {

    String group() default "DEFAULT_GROUP";
}

I also have a listener class like below:

public class MyCustomAnnotationListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();
        Map<String, Object> myCustomAnnotationBeans = applicationContext.getBeansWithAnnotation(MyCustomAnnotation.class);
    }
}

I have configured my application-context.xml to scan components with MyCustomAnnotation.

<context:include-filter type="annotation" expression="com.annotations.MyCustomAnnotation"/>

I can get the list of beans which are annotated with MyCustomAnnotation during initial startup of my application using getBeansWithAnnotation method in MyCustomAnnotationListener.

My question is why this method returns an empty list when it is triggered the second time.

Thanks


Solution

  • ContextRefreshedEvent should happen once during bootstrapping the context. It will publish the event to the context itself and all of its parent contexts.

    Now its listener (i.e MyCustomAnnotationListener) executes 2 times suggesting that your context may have a parent context .The @MyCustomAnnotation beans are defined in child context , and so the parent context cannot find it and empty list is return when MyCustomAnnotationListener runs for the parent context.

    You may verify if the context are the same using applicationContext.getId().

    BTW : As @MyCustomAnnotation is also marked with @Component , it will be picked up by Spring by default , no need to set the include-filter.