我已经声明了两个相同类类型的 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);
}
}
输出
helloworld2, my.entp.spring.HelloWorld@3a9bba
helloworld1, my.entp.spring.HelloWorld@163f7a1 // why was helloworld1 initialized?
Autowired: my.entp.spring.HelloWorld@3a9bba
如果您观察输出,您可能会注意到 helloworld1
bean 在 helloworld2
为 @Autowired
时被初始化。
我通过删除 @Autowired
进行了测试,它产生了预期的结果:未初始化任何 bean。
最佳答案
直接使用@Autowired
时,注入(inject)方式为byType
。换句话说,容器看到了
@Autowired
private HelloWorld helloworld2;
并尝试在 ApplicationContext
中找到类型为 HelloWorld
的 bean 以注入(inject)。
解析要注入(inject)的 bean 的过程包括获取所有候选 bean,然后创建 bean。所以 bean 是 @Lazy
不会改变任何东西。它们仍然必须被创建才能被注入(inject)。
为了澄清 M. Deinum's 对该问题的评论,您已经给出了 bean 名称。例如,
@Bean(name="helloworld1")
当注入(inject)过程发生时,Spring 将找到所有可以注入(inject)的候选 bean。如果不止一个,它会过滤它们并尝试找到最佳人选。如果不能,它将抛出异常。找到更好的候选者的步骤之一是将 bean 名称与目标字段的名称进行比较。由于您的匹配,将选择名为 helloworld2
的 bean。
通过删除 @Autowired
,永远不会从 ApplicationContext
请求 beans,因此永远不会初始化。
关于java - Spring 延迟加载 - 加载一个 bean 会加载该类的所有 @Lazy bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23125397/