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

相关推荐
架构文摘JGWZ29 分钟前
Java 23 的12 个新特性!!
java·开发语言·学习
拾光师1 小时前
spring获取当前request
java·后端·spring
aPurpleBerry1 小时前
neo4j安装启动教程+对应的jdk配置
java·neo4j
我是苏苏1 小时前
Web开发:ABP框架2——入门级别的增删改查Demo
java·开发语言
xujinwei_gingko2 小时前
Spring IOC容器Bean对象管理-Java Config方式
java·spring
2301_789985942 小时前
Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)
java·开发语言·学习
IT学长编程2 小时前
计算机毕业设计 教师科研信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·毕业设计·springboot·毕业论文·计算机毕业设计选题·计算机毕业设计开题报告·教师科研管理系统
m0_571957582 小时前
Java | Leetcode Java题解之第406题根据身高重建队列
java·leetcode·题解
程序猿小D2 小时前
第二百三十五节 JPA教程 - JPA Lob列示例
java·数据库·windows·oracle·jdk·jpa
Java小白笔记3 小时前
关于使用Mybatis-Plus 自动填充功能失效问题
spring boot·后端·mybatis