Spring Bean总结
Spring Bean总结
Spring Bean Scope
spring
bean的作用域范围最常用的是单例和原型,使用@Scope("prototype")
指定即可。
- singleton(单例):spring的scope默认是单例
- prototype(原型):每一次对该bean的请求都会创建一个新的实例
- request:http请求每次都会创建一个新的实例
- session:http请求每个新的session都会创建一个新的实例
Spring Bean生命周期
spring只会帮我们去管理单例的bean的整个生命周期。
对于原型的bean,spring在走完创建的流程,交给使用者后,bean的后续生命周期的流程就交由使用者进行管理了。
所以下图的spring对单例的整个生命周期的管理。
图中的调用xx类的yy方法
是指此bean实现了此接口才会调用。
对于要自己管理对象的生命周期的话,除了第四步bean本来就在自己手上,其余的方法都是要自己调用的。
所以常用的主要就是一下这几点。
- spring负责调用构造函数创建对象
- spring负责注入依赖bean
- spring负责调用我们自定义的bean的初始化函数(如果有)
- spring负责注入bean,把bean交到使用者手上
- spring负责在容器关闭时调用我们自定义的bean的销毁函数(如果有)
Spring循环依赖
spring的循环依赖问题是指几个bean直接相互引用,例如A引用B,B又引用A,或者直接是A引用自己。
spring的依赖注入有三种入口:构造函数注入,成员变量注入和setter注入。
而spring只能解决单例的成员变量或者setter注入问题。
首先,无论bean的作用域是哪种,构造函数注入的循环应用都是无解的。
而对于作用域是原型的,则无论哪种注入方式也都是无解的。
因为例如A1引用B1,B1又引用A2,A2->B2,如此反复无穷无尽也。
所以对于以上无解情形spring检测出来会抛异常,而有解的只有单例的成员变量和setter注入。
spring循环依赖的解决办法是通过三个map做bean的缓存实现的。
1 |
|
例如下图的AB互相引用的例子
- 从singletonObjects里检查A是不是已经初始化完成,是的话则返回
- 否则创建A,将A封装到A工厂里,放到工厂map
- 初始化A,发现A依赖B
- 从singletonObjects里检查B是不是已经初始化完成,是的话则返回
- 否则创建B,将B封装到B工厂里,放到工厂map
- 初始化B,发现B依赖A
- 发现A在工厂map里,将A移到早期引用map里,工厂map移除A工厂
- B在早期引用注入A,B完成初始化
- A在单例池注入B,A完成初始化
参考文章: