一、bean的概念
1.Spring官方文档对于bean的解释为:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.
翻译过来就是:在Spring中,形成你的应用程序的主干,并且被Spring IoC容器管理的对象叫做bean;一个bean就是被Spring IoC容器实例化、装配并且管理的对象。
2.从官网文档我们可以知道:
- bean是被Spring IoC容器管理的一个对象
- bean能够被Spring IoC容器实例化并装配
二、Spring IoC的概念
1.IoC:Invention of Control;控制反转;也叫做DI:Dependency Injection:依赖注入
2.为什么出现IoC的概念?
- 对于软件工程而言,可能需要多个系统之间、多个模块之间、多个对象之间的相互耦合,共同组成一个企业级应用工程,随着耦合度越来越高,极容易牵一发而动全身的情况,只要其中一小部分出现问题,整个工程便无法实现功能。为了解决这种系统、模块、对象之间的耦合度过高的问题,提出了IoC的概念。如今IoC的理论在Spring中得到充分的展现。
- IoC其实就相当于一个第三方中间件,对象之间都根据这个第三方形成依赖关系。
- 这种体系的好处在于:之前对象之间组成依赖关系,若其中一个对象出现问题,则全局无法开展;而使用一个第三方中间件之后,尽管其中一个对象出现问题,其他模块都能够正常工作。
- 因此,可以将IoC容器看作是所有对象之间的粘合剂,这些对象的控制权都交给了IoC,这样就叫做控制反转。
- 举个例子,若对象A与对象B存在依赖关系,引入IoC后,控制权交给了IoC;当A需要B时,不需要主动与对象B进行交互,而直接让IoC创建一个对象注入到A所需要B的位置。A获取B的方式由主动创建转为被动接受注入。这,就是IoC。同时也引出了IoC的同义名词-依赖注入。
对Spring IoC更系统的讲解请参考:https://www.cnblogs.com/superjt/p/4311577.html
三、bean的实例化、装配、管理
1.bean的创建
* bean:配置一个bean对象,将对象交给IOC容器管理
* 包含的属性:
* id:bean的唯一标识,不能重复
* class:设置bean对象所对应的类型(只能为类,不能为接口)
<bean id="hellospring" class="com.gz.pojo.HelloWorld"></bean>
2.bean的获取
* 根据bean id 获取
* 根据bean 类型 获取(用得最多)
* 根据 bean id 和 类型 获取
@Test
public void testHelloWorld(){
//1.获取IOC容器:使用ApplicationContext的子类:ClassPathXmlApplicationContext
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.获取IOC容器中的bean对象:使用getBean()方法
//获取bean对象的三种方式
//1.根据bean的 ID 获取
HelloWorld bean1 = (HelloWorld) ioc.getBean("hellospring");
//2.根据bean的 类型 获取
HelloWorld bean2 = ioc.getBean(HelloWorld.class);
//3.根据bean的 ID + 类型 获取
HelloWorld bean3 = ioc.getBean("hellospring", HelloWorld.class);
bean1.sayHello();
bean2.sayHello();
bean3.sayHello();
}
3.获取bean常见问题
1. bean中class类不提供无参构造器时因反射失败而报错
2. 根据bean 类型 获取时,要求IOC容器中一定要有一个、并且有且只有一个类型匹配的bean。若bean中出现两个id不同但相同class,会报错
3. 如果组件类实现了接口,能根据接口类型获取bean吗?
* 可以;前提bean是唯一的
4. 如果一个接口有多个实现类,这些实现类都配置了bean,根据接口类型能获取bean吗?
* 不能,因为bean不唯一
5. 总结:根据类型获取bean时,在满足bean唯一性的前提下,只看:对象 instanceof 指定的类型的返回结果,只要返回的事true就可以认定为和类型匹配,能够获取到(由于是面向接口编程,很多时候都是通过接口类型获取bean的)
* 即:通过bean的类型、bean所继承的类的类型、bean所实现的接口的类型都可以获取bean
4.bean的作用域
* 在Spring中可以通过配置bean标签的scope属性指定bean的作用域范围
* singleton(默认):在iooc容器中,bean的对象始终为单实例(用得多)
<bean id="studentTest" class="com.gz.spring.pojo.Student" scope="singleton">
* prototype:bean在ioc容器中有多个实例
<bean id="studentTest" class="com.gz.spring.pojo.Student" scope="prototype">
* 若在WebApplicationContezr环境下还会有另外两个作用域(不常用)
* request:在一个请求范围内有效
* session:在一个会话范围内有效
5.bean的生命周期
* 第一步:实例化
* 通过反射/工厂模式
* 第二步:依赖注入:即为属性赋值
* 第三步:初始化:需要自定义init_method
* 第四步:销毁:需要自定义destroy_method
* 要想销毁,需要使用configurable ApplicationContext才能调用close
* configurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
//3.生命周期第三步:初始化
public void initMethod(){
System.out.println("生命周期第三步:初始化");
}
//4.销毁
public void destroyMethod(){
System.out.println("生命周期第四步:销毁");
}
<bean id="user" class="com.gz.spring.pojo.User"
init-method="initMethod" destroy-method="destroyMethod"
scope="singleton">
<property name="id" value="1"></property>
<property name="username" value="admin"></property>
<property name="password" value="0111"></property>
<property name="age" value="11"></property>
</bean>
* 补充:在生命周期初始化前后,后置处理器会添加额外的操作;此时在ioc容器中配置后,会对每一个bean起作用(了解)
6.不同作用域对生命周期的影响(从生命周期的角度理解)
* 若bean作用域为单例,则生命周期的前三步:实例化、依赖注入、初始化,会在获取ioc容器时执行
* 若bean作用域为多例,则生命周期的前三步会在获取bean时执行
总结
总而言之,关于bean这个概念就如本文第一部分所讲,是一个被Spring IoC容器管理的对象,是组成应用程序的主干;但这样理解毕竟比较抽象,要想对这一个概念有足够清晰的认识,需要多思考、多灵活运用。