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