spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.77k stars 38.16k forks source link

Improve documentation for `allowEagerInit` parameter in `getBeanNamesForType()` #33740

Closed pop1213 closed 1 month ago

pop1213 commented 1 month ago

Spring version: 6.0.16

This is the documentation for the ListableBeanFactory#getBeanNamesForType method.

allowEagerInit – whether to initialize lazy-init singletons and objects created by FactoryBeans (or by factory methods with a "factory-bean" reference) for the type check. Note that FactoryBeans need to be eagerly initialized to determine their type: So be aware that passing in "true" for this flag will initialize FactoryBeans and "factory-bean" references.

According to the documentation of the getBeanNamesForTypemethod, the bean myBeanCreater should be eagerly initialized. However, in the following test it was not.

public interface BaseBean {
}
@AllArgsConstructor
public class MyBean implements BaseBean {
    private String name;
}
public class MyBeanCreator {

    public MyBeanCreator() {
        System.out.println("MyBeanCreator initialized");
    }

    public BaseBean createMyBean(){
        return new MyBean("test");
    }
}

beans.xml:

    <bean id="myBeanCreator" class="com.example.wemvc.MyBeanCreator" lazy-init="true" ></bean>
    <bean  id="myBean" lazy-init="true"  factory-bean="myBeanCreator" factory-method="createMyBean"></bean>

Test:

    @Test
    public void test(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
        context.setConfigLocation("beans.xml");
        context.refresh();
        //allowEagerInit  is true and `myBeanCreator `is still not initialized 
       // beanNamesForType = []
        String[] beanNamesForType = context.getBeanNamesForType(MyBean.class, true, true);

    }
jhoeller commented 1 month ago

Note that eager initialization refers to the "factory-bean" as the bean containing the factory method - which may be in turn an implementation of the FactoryBean interface. Only in such a scenario where it needs to be initialized in order to have a reliable factory method to introspect, it will initialize that target bean then. However, it will not perform eager calls to a factory method just to find out whether the runtime bean instance produced by it has a more specific type than what the method return type declares, and it also won't invoke constructors of factory beans if the method signature indicates the type already. I'll revise the getBeanNamesForType javadoc to be more specific about the actual effect there.