首页 > 解决方案 > 为什么`SpringApplication.run`不懒惰地创建bean?

问题描述

如果您在项目中定义了具有单例范围的组件类,并且main()除了调出应用程序上下文之外什么都不做,例如:

ConfigurableApplicationContext context = SpringBootApplication.run(MyMainClass.class, args)

context将已经指向ApplicationContext包含这些类的单例实例的一个。因此,无论您键入多少次,context.getBean(MyContainerClass.class)您都会得到相同的MyContainerClass.

但是该对象的创建可能非常繁重,甚至依赖于运行时约束(数据库连接、网络套接字管理、工作)。我知道重载构造函数不是很好的编程习惯,但即使在 POJO 中,它也可能发生。

我想知道是否有一种特殊的逻辑可以在创建上下文时立即创建单例,而不是第一次getBean()调用。也许 SpringBoot 给程序员的合同说:“如果你用 注释了一个类@Component,你真的应该在某个时候检索 bean:我假设你知道这一点,并且愿意在上下文出现时吃掉构建成本带大。” 也许不吧。没有把握。

标签: javaspring-bootinversion-of-controlapplicationcontextspring-bean

解决方案


实际上 Spring Boot (2.3.3) 可以延迟加载 @Beans。只需将以下属性添加到您的application.properties文件中。初始化应该延迟执行。

spring.main.lazy-initialization = true

在整个应用程序中启用延迟初始化可能会产生积极和消极的影响。请参阅Baeldung描述的延迟初始化的效果:

  1. 延迟初始化可能会减少应用程序启动时创建的 bean 数量——因此,我们可以提高应用程序的启动时间

  2. 由于在需要它们之前不会创建任何 bean,我们可以掩盖问题,让它们在运行时而不是启动时

  3. 这些问题可能包括内存不足错误、配置错误或类定义发现错误

  4. 此外,当我们在 Web 上下文中时,按需触发 bean 创建会增加 HTTP 请求的延迟——bean 创建只会影响第一个请求,但这可能会对负载平衡和自动缩放产生负面影响。


推荐阅读