在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实例是否相同或不同 |

相关推荐
智驭未来掌门人4 分钟前
利用FFmpeg快速实现一个RTSP推流服务器
后端
垚垚学技术_聚焦云原生17 分钟前
K8s Pod 完整生命周期详解
后端
JavaGuide21 分钟前
Github 史诗级故障,与此同时,Cursor 版「GitHub」正式上线!
前端·后端
Java成神之路-24 分钟前
深入理解三大高频队列:ArrayDeque、LinkedList、PriorityQueue 方法、特性与场景选择
java
不一样的少年_24 分钟前
修了 Bug、做了重构,为什么老板还是觉得你没产出?
前端·后端·程序员
roman_日积跬步-终至千里33 分钟前
【资源控制】自助查询的智能路由
java·大数据·数据库
水深火乐43 分钟前
安全地生成验证码、密码和 Token
后端
小强19881 小时前
SQL Server 慢查询怎么定位?一套从“卡”到“快”的完整排查流程
后端
水深火乐1 小时前
interface和any
后端
步行cgn1 小时前
MyBatis Error evaluating expression ‘ids‘. Return value (3) was not iterable 错误详
java·后端