spring加载机制及流程
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,
//手动注册几个特殊的 bean, 类加载器,Aware 接口初始化处理类, 事件监听器等等
prepareBeanFactory(beanFactory);
// 这步比较关键,解析注解和xml配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
// 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
postProcessBeanFactory(beanFactory);
// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
// 还有BeanDefinitionRegistryPostProcessor这个实现类,可以进行bean配置的注册
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor 的实现类
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
registerBeanPostProcessors(beanFactory);
// 初始化当前 ApplicationContext 的 MessageSource,国际化
initMessageSource();
// 初始化当前 ApplicationContext 的事件广播器
initApplicationEventMulticaster();
// (钩子方法)具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
// 注册事件监听器,监听器需要实现 ApplicationListener 接口
registerListeners();
// 重点,重点,重点 初始化所有的 singleton beans(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
{
//创建bean,并返回,如果是普通bean直接返回,如果是factorybean,返回创建的实例对象
//prototype原型bean,则抛异常
getBean()->getSingleton()->获取单例缓存,判断
-------------
有则直接,getObjectForBeanInstance
-------------
没有则,判断是否已创建这个实例了,有了则抛异常,防止循环依赖
然后bean获取进行了父类委托和缓存优化
获取BeanDefinition的dependsOn依赖关系,首先加载所有依赖getBean(),
然后判断bean是Singleton还是Prototype,
--------------
Singleton,
1.先锁定singletonObjects,如果里面有对象直接返回,
2.否则先把当前bean加入到已创建的单例集合里,再createBean(),释放集合里的记录,
3.最后添加进singletonObjects,从singletonFactories和earlySingletonObjects里删除
--------------
Prototype,先把当前bean加入到已创建的多例集合里,再createBean(),释放集合里的记录最后都需要调用getObjectForBeanInstance()获取实例getSingleton():
1.取singletonObjects里的记录,有则直接返回,
2.取earlySingletonObjects里的记录,有则直接返回
3.如果是空的,则取singletonFactories里的FactoryBean对象,并从singletonFactories删除,加入earlySingletonObjectscreateBean():
1.执行InstantiationAwareBeanPostProcessor(Class> beanClass, String beanName)生命周期
如果上一步返回的bean不为空,则调用BeanPostProcessor的after回调,并直接返回bean实例
2.否则继续执行doCreateBean方法,调用createBeanInstance()生成BeanWrapper对象(提供javabean对象的属性填充接口等),
执行MergedBeanDefinitionPostProcessor(RootBeanDefinition beanDefinition, Class> beanType, String beanName)的回调,
3.执行SmartInstantiationAwareBeanPostProcessor(Object bean, String beanName)回调
4.如果不存在singletonObjects中,则把当前bean存入singletonFactories,从earlySingletonObjects删除
5.执行populateBean()
autowireByName和autowireByType注入所有依赖getBean()
执行InstantiationAwareBeanPostProcessor(PropertyValues pvs, Object bean, String beanName)和
(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)回调
6.执行initializeBean()
执行BeanPostProcessor的before(Object bean, String beanName)回调
执行afterPropertiesSet()回调
执行BeanPostProcessor的after(Object bean, String beanName)回调
7.注册bean关闭的生命周期回调getObjectForBeanInstance():
1.factoryBeanObjectCache里有记录则直接返回
2.没有则从factorybean里获取object并存入factoryBeanObjectCache,然后返回}
// 最后,广播事件,ApplicationContext 初始化完成,不展开
finishRefresh();
循环依赖问题 Spring为了解决单例的循环依赖问题,addSingletonFactory方法使用了三级缓存,这三级缓存分别指:
singletonFactories : 单例对象工厂的cache 一级缓存:用于存放完全初始化好的 bean
earlySingletonObjects :提前暴光的单例对象的Cache 二级缓存:存放半成品的Bean,半成品的Bean是已创建对象,但是未注入属性和初始化。用于解决循环依赖
singletonObjects:单例对象的cache 三级级缓存:存的是Bean工厂对象,用来生成半成品的Bean并放入到二级缓存中。用于解决循环依赖
A 创建过程中需要 B,于是 A 将自己放到三级缓里面 ,去实例化 B
B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了!
然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
B 顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
然后回来接着创建 A,此时 B 已经创建结束,直接从一级缓存里面拿到 B ,然后完成创建,并将自己放到一级缓存里面
我们可以知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。这个cache的类型是ObjectFactory。这里就是解决循环依赖的关键,发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。
所以spring不支持构造器循环依赖和prototype field属性注入循环依赖
非单例Bean默认不会初始化
为什么采用三级缓存而不是二级? 【spring加载机制及流程】包装一层ObjectFactory对象不提前创建好代理对象,在出现循环依赖被其他对象注入时,才实时生成代理对象。这样在没有循环依赖的情况下,Bean就可以按着Spring设计原则的步骤来创建。执行一些生命周期方法回调。
Spring容器会将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- SpringBoot调用公共模块的自定义注解失效的解决
- 解决SpringBoot引用别的模块无法注入的问题
- 使用composer自动加载类文件
- 2018-07-09|2018-07-09 Spring 的DBCP,c3p0
- 深入理解|深入理解 Android 9.0 Crash 机制(二)
- spring|spring boot项目启动websocket
- Spring|Spring Boot 整合 Activiti6.0.0
- Spring集成|Spring集成 Mina
- springboot使用redis缓存