spring加载机制

16 篇文章 0 订阅
// 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
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删除,加入earlySingletonObjects
        
    createBean():
        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默认不会初始化

为什么采用三级缓存而不是二级?
包装一层ObjectFactory对象不提前创建好代理对象,在出现循环依赖被其他对象注入时,才实时生成代理对象。这样在没有循环依赖的情况下,Bean就可以按着Spring设计原则的步骤来创建。执行一些生命周期方法回调。
Spring容器会将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值