Spring延迟加载 - 加载一个bean加载该类的所有@Lazy bean

pha*_*ani 7 java spring spring-bean

我已经声明了两个相同类类型的bean.初始化它们@Lazy.@Autowiring它们中的一个bean也自动初始化了另一个bean.我很惊讶地看到这种行为.只是好奇了解更多有关机制的信息.

//bean
public class HelloWorld {
    public HelloWorld(String msg){
         System.out.println( msg + ", " + this);
    }   
}

@Configuration
@Lazy
public class SpringAppContext {

     @Bean(name="helloworld1")
     public HelloWorld helloworld1(){
        return new HelloWorld("helloworld1");
     }  
     @Bean(name="helloworld2")
     public HelloWorld helloworld2(){
        return new HelloWorld("helloworld2");
     }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringAppContext.class})
public class SpringBeanLazyLoadTest {
     @Autowired
     private HelloWorld helloworld2;

     @Test // this test is lame but just trying out.
     public void print(){
        System.out.println("Autowired: " + helloworld2);
     }
}
Run Code Online (Sandbox Code Playgroud)

产量

helloworld2, my.entp.spring.HelloWorld@3a9bba
helloworld1, my.entp.spring.HelloWorld@163f7a1 // why was helloworld1 initialized?
Autowired: my.entp.spring.HelloWorld@3a9bba
Run Code Online (Sandbox Code Playgroud)

如果你观察输出,你可能会注意到helloworld1,当豆被初始化helloworld2@Autowired.

我通过删除测试@Autowired并且它产生了预期的结果:初始化没有bean.

Sot*_*lis 9

@Autowired直接使用时,注射方法是byType.换句话说,容器看到了

 @Autowired
 private HelloWorld helloworld2;
Run Code Online (Sandbox Code Playgroud)

并尝试HelloWorldApplicationContext注入中找到类型的bean .

解析要注入的bean的过程包括获取包含创建bean的所有候选bean.所以豆子@Lazy不会改变任何东西.它们仍然必须被创建才能被注入.

为了澄清M. Deinum对这个问题评论,你已经给出了豆子的名字.例如,

 @Bean(name="helloworld1")
Run Code Online (Sandbox Code Playgroud)

当注射过程发生时,Spring将找到所有可注射的候选bean.如果有多个,它将​​过滤掉它们并尝试找到最佳候选者.如果不能,则会抛出异常.找到更好的候选者的步骤之一是将bean名称与目标字段的名称进行比较.由于您的匹配,helloworld2将选择名为bean的bean .

通过删除@Autowired,永远不会从bean请求bean ApplicationContext,因此永远不会初始化.