`SpringApplication.run` 为什么不会懒加载创建这些 Bean?

huangapple go评论76阅读模式
英文:

Why does `SpringApplication.run` not create the beans lazily?

问题

如果您在项目中使用单例作用域定义了组件类,并且在 main() 中除了启动应用程序上下文之外什么都不做,例如:

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

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

但是,创建该对象可能会非常耗费资源,甚至依赖于运行时约束(数据库连接、网络套接字管理等)。我理解过度使用构造函数不是很好的编程实践,但即使在普通的POJO中,它也可能发生。

我想知道是否存在一种特定的逻辑,可以在上下文创建时立即创建单例,而不是在第一次调用 getBean() 时创建。也许SpringBoot向程序员提供了这样的契约:“如果您已经用 @Component 注解了一个类,您确实应该在某个时候检索该bean:我会假设您知道这一点,并愿意在上下文启动时承担构造成本。”也许不是。不确定。

英文:

If you have defined component classes in your project with singleton scope and do nothing in your main() besides bringing up the application context, e.g with:

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

context will already be pointing to an ApplicationContext that contains a singleton instance of those classes. So no matter how many times you type context.getBean(MyContainerClass.class) you will get the same instance of MyContainerClass.

But the creation of that object might be quite heavy, and even dependent on runtime constraints (database connections, network socket management, the works). I understand that it is not very good programming practice to overload a constructor but, even in POJO, it can happen.

I was wondering whether there was a particular kind of logic to creating the singletons immediately when the context is created, instead of the first time getBean() is called. Maybe there's a contract from SpringBoot to the programmer that says: "If you have annotated a class with @Component, you really should retrieve the bean at some point: I will assume you know this and are willing to eat the construction cost when the context is being brought up." Maybe not. Not sure.

答案1

得分: 1

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

spring.main.lazy-initialization = true

在整个应用程序中启用惰性初始化可能会产生积极和消极的影响。有关惰性初始化效果的详细信息,请参见Baeldung的描述:

  1. 惰性初始化可以减少应用程序启动时创建的Bean数量 - 因此,我们可以改善应用程序的启动时间。

  2. 由于直到需要时才创建任何Bean,因此我们可以在运行时而不是启动时解决问题。

  3. 问题可能包括内存不足错误、配置错误或类定义未找到错误。

  4. 此外,当我们处于Web环境中时,按需触发Bean创建将增加HTTP请求的延迟 - Bean的创建仅影响第一个请求,但这可能对负载平衡和自动扩展产生负面影响。

英文:

actually the Spring Boot (2.3.3) can load the @Beans lazily. Just add the property below to your application.properties file. The initialization should be performed lazily.

spring.main.lazy-initialization = true

Enabling lazy initialization in the whole application could produce both positive and negative effects. See the effects of Lazy Initialization described by Baeldung:

  1. Lazy initialization may reduce the number of beans created when the application is starting – therefore, we can improve the startup time of the application

  2. As none of the beans are created until they are needed, we could mask issues, getting them in run time instead of startup time

  3. The issues can include out of memory errors, misconfigurations, or class-definition-found errors

  4. Also, when we're in a web context, triggering bean creation on demand will increase the latency of HTTP requests – the bean creation will affect only the first request, but this may have a negative impact in load-balancing and auto-scaling.

huangapple
  • 本文由 发表于 2020年9月22日 23:26:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/64012896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定