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池”中清除掉。

    推荐阅读