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

标签 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);
     }
}

输出

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/

相关文章:

java - BeanDefinitionRegistryPostProcessor - 如何将 @Configuration 类注册为 BeanDefinition 并同时注册它的 @Beans

java - 通过嵌套类发送变量

java - 我的代码中的 NumberFormatException

java - 无法使用 content-type=application/x-www-form-urlencoded 获取请求正文

java - 为什么 Spring Boot 中父类(super class)上的 @Bean 泛型创建方法的调用晚于子类上的创建方法?

java - Spring DeferredImportSelector 在任何配置之前运行

java - 如何在 Hadoop-.20 api 中指定 KeyValueTextInputFormat 分隔符?

java - 为什么我必须在 spring data jpa 中将 @Modifying 与 @Transactional 一起使用?

java - 如何显示与JPS页面不同的URL链接?

java - Kubernetes:如何使用 K8 的 API 从代码中访问当前正在运行的 pod 的标签值?