在Spring中,相同类型不同ID的bean,与相同ID多次获取bean的区别和联系

1. 理论分析

1.1 相同类型不同ID的bean

当在Spring容器中为相同的类定义了多个不同的bean ID时,每个bean实例都是独立的。这意味着,即使它们的类型相同,它们的属性和状态可以完全不同。

获取方式:

如果相同类定义了多个Bean时,或者相同接口有多个实现类时,需要根据beanId 的方式才能获得组件,或者根据beanid并同时指定bean的类型获得组件,仅通过指定bean类型是获取不到组件的,会报错NoUniqueBeanDefinitionException

特点:

  • 独立实例:即使类型相同,但由于bean ID不同,它们是不同的对象,每个bean都有独立的属性配置。
  • 可配置不同的属性:你可以为同一类型的多个bean配置不同的属性,达到差异化的目的。
  • 适用场景:通常用于同一类的不同实例,具有不同的业务逻辑或属性需求的场景。

2.2 相同ID多次获取bean

当你多次通过相同的ID获取bean时,行为取决于bean的作用域(scope) 。在Spring中,默认的作用域是单例(singleton) ,即容器内每个bean ID只会有一个实例。因此,无论你调用多少次getBean("beanId"),都会返回同一个实例。如果是多例(prototype),则相反。

作用域解释:

  • singleton(单例):这是Spring的默认作用域。一个bean在整个容器生命周期内只有一个实例,多次获取时返回相同的对象。
  • prototype(多例) :每次调用getBean()时都会返回一个新的实例,bean的状态不共享。

特点:

  • 单例作用域:默认情况下,Spring容器中的bean是单例的,无论你获取多少次,返回的都是同一个对象。
  • 多例作用域 :如果将bean的作用域设置为prototype,则每次调用getBean()都会创建一个新的实例。
  • 适用场景:单例作用域适用于在整个应用程序中共享状态的bean,而原型作用域适用于每次都需要新实例的情况,如处理短暂任务的对象。

2. 代码实践

2.1 接口

java 复制代码
public interface HappyComponent {
    void doWork();
}

2.2 实现类

java 复制代码
public class HappyComponentImpl implements HappyComponent {
    public void doWork(){
        System.out.println("HappyComponent is doWork");
    }
}

2.3 IOC配置

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 组件的信息ioc的配置 -> applicationContext读取了 -> 实例化对象
        ioc 的配置一定是实现类 真正要进行实例化
-->
    <bean id="happyComponent1" class="com.atguigu.ioc_03.HappyComponentImpl"/>
    <bean id="happyComponent2" class="com.atguigu.ioc_03.HappyComponentImpl" scope="prototype"/>
</beans>

2.4 测试

java 复制代码
@Test
    public void test_03_2(){
        // 1 创建IOC容器对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext();
        applicationContext.setConfigLocation("spring-03.xml");
        applicationContext.refresh(); //ioc di 的动作

        // 2. 读取ioc容器的组件
            // 方案2 根据beanId 同时指定bean的类型 Class
        HappyComponentImpl happyComponent1_1 = applicationContext.getBean("happyComponent1", HappyComponentImpl.class); // 单例模式
        HappyComponentImpl happyComponent1_2 = applicationContext.getBean("happyComponent1", HappyComponentImpl.class); // 单例模式
        HappyComponentImpl happyComponent2_1 = applicationContext.getBean("happyComponent2", HappyComponentImpl.class); // 多例模式
        HappyComponentImpl happyComponent2_2 = applicationContext.getBean("happyComponent2", HappyComponentImpl.class); // 多例模式
        happyComponent1_1.doWork();
        happyComponent1_2.doWork();
        happyComponent2_1.doWork();
        happyComponent2_2.doWork();
        System.out.println("happyComponent1_1==happyComponent1_2: "+String.valueOf(happyComponent1_1==happyComponent1_2));
        System.out.println("happyComponent2_1==happyComponent2_2: "+String.valueOf(happyComponent2_1==happyComponent2_2));
        System.out.println("happyComponent1_1==happyComponent2_1: "+String.valueOf(happyComponent1_1==happyComponent2_1));
    }

2.5 测试结果

java 复制代码
HappyComponent is doWork
HappyComponent is doWork
HappyComponent is doWork
HappyComponent is doWork
happyComponent1_1==happyComponent1_2: true
happyComponent2_1==happyComponent2_2: false
happyComponent1_1==happyComponent2_1: false

3.结论

通过实验不难看出,相同类型不同ID的Bean组件相互独立,相同ID多次获取的组件是否独立要看作用域scope的设置,如果是单例则为同一个对象,否则为独立对象。

|--------|---------------------------|------------------------------|
| 区别 | 相同类型不同ID | 相同ID多次获取 |
| 实例独立性 | 每个bean都有独立的属性和状态,不共享 | 取决于作用域,单例时返回同一实例,多例则各自返回独立实例 |
| 适用场景 | 需要相同类型但配置不同的多个实例 | 单例bean用于共享状态,多例bean用于非共享实例 |
| 作用域的影响 | 作用域不会影响不同ID的bean,它们始终是独立的 | 作用域决定每次获取的bean实例是否相同或不同 |

相关推荐
ExiFengs1 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj1234567892 分钟前
JDK1.8新增特性
java·开发语言
捂月8 分钟前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
繁依Fanyi13 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
慧都小妮子24 分钟前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net
m512729 分钟前
LinuxC语言
java·服务器·前端
IU宝33 分钟前
C/C++内存管理
java·c语言·c++
瓜牛_gn34 分钟前
依赖注入注解
java·后端·spring
hakesashou35 分钟前
Python中常用的函数介绍
java·网络·python
佚先森44 分钟前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html