目录
Spring Bean的生命周期是从Bean实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。
大体分为三个阶段
-
Bean的实例化:Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射进行实例化
-
Bean的初始化阶段:Bean创建之后还仅仅是一个“半成品”,还需要对Bean实例的属性进行填充,执行一些Aware接口方法,执行BeanPostProcessor方法,执行InitializingBean接口的初始化方法,执行自定义初始化init方法等
-
-
Bean的完成阶段:经过初始化阶段,Bean就成为一个完整的Spring Bean,被存储到单例池中,完成了Spring Bean的整个生命周期
Bean实例属性填充
BeanDefinition中有对当前Bean实体属性的信息注入通过属性propertyValues进行存储
Spring在进行属性注入时,会分为如下几种情况:
-
注入普通属性,String,int或储存基本类型的集合时,直接通过set方法的反射设置进去
-
注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则注入对象Bean实例(完成了整个生命周期)后,再进行注入操作
-
注入双向对象引用属性时,就比较复杂了,涉及到循环引用(循环依赖)
多个实体之间相互依赖并形成闭环的情况叫做“循环依赖” 也叫做“循环引用”
例如:
<bean id="userService" class="com.xfy.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.xfy.dao.Impl.UserDaoImpl" scope="singleton">
<property name="userService" ref="userService"></property>
</bean>
如何解决循环引用,上述流程会导致内存占满,不停的创建Bean对象
三级缓存
Spring提供了三级缓存存储完整Bean实例和半成品Bean实例,用于解决循环引用问题在DefaultListableBeanFactory的上四级父类DefaultSingletonBeanRegistry中提供如下三个Map
三级缓存:String ->BeanName ObjectFactory<?> -> Bean半成品
UserService和UserDao循环依赖过程结合三级缓存描述:
-
UserService实例化对象,但尚未初始化,将UserService存储到三级缓存;
-
UserService属性注入,需要UserDao,从缓存中获取,没有UserDao
-
UserDao实例化对象,但尚未初始化,将UserDao存储到三级缓存
-
UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移入二级缓存
-
UserDao执行其他生命周期过程,最终成为一个完整Bean,存储到一级缓存,删除二三级缓存
-
UserService注入UserDao
-
UserService执行其他生命周期过程,最终成为一个完整Bean,存储到一级缓存,删除二三级缓存