Affects: 5.3.x

When a bean is defined using a static method, findAnnotationOnBean finds an annotation from the @Configuration class to which the static @Bean method belongs. The annotation is not found if the @Bean method is not static.

The following tests illustrate this behavior:

package com.example;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.junit.jupiter.api.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static org.assertj.core.api.Assertions.assertThat;

class FindAnnotationOnBeanTests {

    @Test
    void beanDefinedInInstanceMethodDoesNotHaveAnnotationsFromItsConfigurationClass() {
        beanDoesNotHaveAnnotationsFromItsConfigurationClass(InstanceBeanMethodConfiguration.class);
    }

    @Test
    void beanDefinedInStaticMethodDoesNotHaveAnnotationsFromItsConfigurationClass() {
        beanDoesNotHaveAnnotationsFromItsConfigurationClass(StaticBeanMethodConfiguration.class);
    }

    void beanDoesNotHaveAnnotationsFromItsConfigurationClass(Class<?> config) {
        try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(config)) {
            ExampleAnnotation annotation = context.getBeanFactory().findAnnotationOnBean("exampleBean",
                    ExampleAnnotation.class);
            assertThat(annotation).isNull();
        }
    }

    @Configuration
    @ExampleAnnotation
    static class StaticBeanMethodConfiguration {

        @Bean
        static String exampleBean() {
            return "example";
        }

    }

    @Configuration
    @ExampleAnnotation
    static class InstanceBeanMethodConfiguration {

        @Bean
        String exampleBean() {
            return "example";
        }

    }

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    static @interface ExampleAnnotation {

    }

}

beanDefinedInInstanceMethodDoesNotHaveAnnotationsFromItsConfigurationClass passes but beanDefinedInStaticMethodDoesNotHaveAnnotationsFromItsConfigurationClass fails.

Comment From: 284831721

I can't understand, so, which test result is expected? first or second.

From the findAnnotationOnBean method's comment describe as follow, I think test 1 is the expected behavior, am I right?

/**
     * Find an {@link Annotation} of {@code annotationType} on the specified bean,
     * traversing its interfaces and super classes if no annotation can be found on
     * the given class itself, as well as checking the bean's factory method (if any).
     * @param beanName the name of the bean to look for annotations on
     * @param annotationType the type of annotation to look for
     * (at class, interface or factory method level of the specified bean)
     * @return the annotation of the given type if found, or {@code null} otherwise
     * @throws NoSuchBeanDefinitionException if there is no bean with the given name
     * @since 3.0
     * @see #getBeanNamesForAnnotation
     * @see #getBeansWithAnnotation
     */

Comment From: wilkinsona

Both should pass. The tests are illustrating the described difference between static and instance bean methods.