何时实例化Spring Bean?

37
ApplicationContext ctx = new ClassPathXmlApplicationContext(
    "com/springinaction/springidol/spring-idol.xml");
Performer performer = (Performer) ctx.getBean("duke");
performer.perform();
在上面的代码中,bean 是在 ApplicationContext 创建时实例化还是在调用 getBean() 时实例化?
8个回答

49

假设这个Bean是单例模式,并且没有配置延迟初始化,那么它会在上下文启动时创建。 getBean() 只是将其取出。

仅当首次引用时才会初始化延迟初始化的Bean,但这不是默认设置。作用域Bean(例如原型作用域)也仅在首次引用时才会被创建。


如果使用BeanFactory,那么bean是否会被延迟加载? - java_geek
2
@java_geek:嗯,BeanFactory只是一个接口,它取决于你使用哪种实现,但通常情况下,大多数(如果不是全部)BeanFactory实现都是如此。 - skaffman
@Skaffman:对不起,我理解如果bean的范围是singleton,它会在新的applicationContext中创建。但是如何测试是否已创建?在原型中,我调用了getBeanDefinitionNames,它仍然出现。 - Adam

17
根据Spring 文档,ApplicationContext实现的默认行为是在启动时急切地预先实例化所有单例bean。同时,您也可以将它们设置为懒加载。

这是单例Bean的行为。但普通Bean的行为是什么? - java_geek
2
@java_geek:单例模式是正常的。它们是默认的。对于你来说什么才是正常的呢? - skaffman
我想知道bean是否设置了singleton=false。 - java_geek

15

参考文献:

下面是有关bean创建时机的简要说明:

  • 默认为单例作用域的bean,如果其lazy-init属性未设置为true(默认为false),则在应用程序上下文创建时被构造。
  • 如果将单例作用域的bean的lazy-init属性设置为true,则在首次请求时构造该bean。
  • 在任何其他作用域中设置的bean将在首次请求时(对于该作用域)创建。

3
  1. 默认情况下,所有的bean都是单例模式,所以当应用程序上下文被创建时,它们都会被预加载。如果有任何一个单例bean设置了lazy-init="true"属性,它将会被延迟加载,也就是说,它将在第一次调用getBean方法时实例化。

  2. 对于其他作用域,只有在请求时才会实例化bean。


2

这取决于您使用getBean()方法调用的Bean的范围。 如果是“Singleton”,则由ApplicationContext预先实例化。

如果您正在使用BeanFactory作为IOC容器,则它使用延迟初始化,只有在调用getBean()方法时才会实例化Bean。

这是ApplicationContext相对于BeanFactory的优点,因为它解决了循环依赖问题。


嗨@Shubham,我是Spring的初学者。我想知道如果一个bean是原型作用域,那么它只有在调用getBean时才会被实例化,对吗?我观察到即使我们不使用getBean,单例也会被创建? - krr

1

默认情况下,Spring ApplicationContext 在应用程序启动时急切地创建和初始化所有“单例作用域”bean。ApplicationContext 使 bean 在 BeanFactory 中可用。getBean() 返回 bean 的实例。


0

默认情况下,它在上下文启动时创建,但顺序取决于依赖关系。 如果我们有以下类:

@Component
public  class A{

}

@Component
public class B{
    @Autowired
    A a;

}

在创建类B之前,需要先创建类A,因为类B依赖于类A。


0

基本上,当运行ApplicationContext时,它会自动创建所有已注释的bean并为您准备好使用。

如果您不需要其中的某些bean,您可以使用@Lazy进行注释,并且它们在运行应用程序时将不会被实例化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接