Spring创建相同类的两个对象?

img

img

img

使用spring创建同类的两个对象,创建bean对象时候调用该类的无参构造方法,使用一个ApplicationContext对象获取两个bean对象的时候只调用了一次无参构造,分别用两个ApplicationContext对象获取两个bean对象的时候调用了两次无参构造,请问是因为使用一个ApplicationContext的时候,一个ApplicationContext中一个类只能有一个bean对象,获取第二个bean的时候没有创建新对象而是把已经创建的bean对象信息覆盖了吗?还是什么别的原理?

在Spring中,每一个ApplicationContext都会维护一个BeanFactory,该BeanFactory会维护所有bean的定义和实例化。当使用ApplicationContext获取bean时,会先查找是否已经存在该bean的实例,如果不存在则通过bean定义信息创建新的实例,如果已经存在则直接返回现有的实例。

在同一个ApplicationContext中,如果要创建两个同类的对象,Spring会先创建一个bean定义信息,然后通过这个bean定义信息创建一个实例。当再次通过该bean定义信息创建bean实例时,Spring会直接返回已经创建好的实例,而不会再次调用构造方法。因此,在使用一个ApplicationContext对象获取两个同类的bean对象时,只会调用一次构造方法。

而当使用两个不同的ApplicationContext对象时,它们维护的BeanFactory是不同的,因此它们会分别创建自己的bean实例。这就是为什么使用两个ApplicationContext对象获取同类的两个bean对象时会调用两次构造方法的原因。

在Spring中,如果使用单例作用域(默认情况下),Spring容器只会在第一次获取bean时创建该bean的一个实例,并将该实例缓存,以后每次请求该bean时,都会返回相同的实例。这是因为Spring容器维护了一个缓存,用于存储单例bean的实例,这个缓存的默认实现是ConcurrentHashMap。因此,当您使用同一个ApplicationContext对象获取同一个bean的实例时,只会调用一次该bean的构造函数,并返回相同的实例。

如果你使用两个ApplicationContext对象分别获取同一个bean的实例,则会创建两个bean实例,因为每个ApplicationContext都维护了自己的单例bean实例缓存。这就是为什么你在使用两个ApplicationContext对象时,会调用两次无参构造函数并创建两个不同的bean实例的原因。

另外,Spring容器中一个类可以有多个bean对象,只需要使用不同的bean名称即可。但是,如果使用默认的单例作用域,则每个bean名称只能对应一个bean实例。如果需要多个实例,可以考虑使用原型作用域。

仅供参考:
在 Spring 中,每个 ApplicationContext 对象都维护着自己的一份 Bean 定义的元信息和一份 Bean 实例的缓存。默认情况下,Bean 实例是单例的,也就是说同一个 Bean 定义在同一个 ApplicationContext 对象中只会被实例化一次。

因此,在同一个 ApplicationContext 中,如果要获取同一个类的两个 Bean 实例,会发现 Spring 只会调用一次该类的无参构造方法,然后缓存该实例,并返回给第二次获取该 Bean 实例的请求。因此,这两个 Bean 实例在 ApplicationContext 中实际上是同一个对象。

而使用两个不同的 ApplicationContext 获取同一个类的两个 Bean 实例,则会分别创建两个实例,因为每个 ApplicationContext 都有自己的 Bean 实例缓存。因此,你在第一个 ApplicationContext 中获取的 Bean 实例和第二个 ApplicationContext 中获取的 Bean 实例是不同的对象。

另外,如果想要在同一个 ApplicationContext 中创建同一类的多个 Bean 实例,可以使用不同的 Bean 名称来区分它们。具体实现可以通过在 Bean 定义中为不同的 Bean 设置不同的名称来实现。例如:

@Component
public class MyComponent {
    // ...
}

@Configuration
public class MyConfiguration {
    @Bean("myComponent1")
    public MyComponent myComponent1() {
        return new MyComponent();
    }

    @Bean("myComponent2")
    public MyComponent myComponent2() {
        return new MyComponent();
    }
}

这样,你就可以通过名称 myComponent1 和 myComponent2 分别获取到两个不同的 MyComponent Bean 实例了。

要看你配置的是不是单例模式才能判断的

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^