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

相关推荐
IT_陈寒16 分钟前
Redis性能翻倍秘籍:10个99%开发者不知道的冷门配置优化技巧
前端·人工智能·后端
LB211219 分钟前
Redis 黑马skyout
java·数据库·redis
洛小豆23 分钟前
Swagger3学习与实践指南
spring boot·后端·spring cloud
豐儀麟阁贵25 分钟前
Java知识点储备
java·开发语言
hrrrrb32 分钟前
【Spring Security】Spring Security 密码编辑器
java·hive·spring
Victor35632 分钟前
Redis(58)如何配置和查看Redis的慢查询日志?
后端
Victor35634 分钟前
Redis(59)Redis的主从复制是如何实现的?
后端
豐儀麟阁贵34 分钟前
2.3变量与常量
java·开发语言
摇滚侠2 小时前
Spring Boot 3零基础教程,自动配置机制,笔记07
spring boot·笔记·后端
兮动人2 小时前
Eureka注册中心通用写法和配置
java·云原生·eureka