Spring的bean生命周期方法
2020-09-16 01:25:00 0 举报
Spring
作者其他创作
大纲/内容
finishBeanFactoryInitialization方法内部最后一行! beanFactory.preInstantiateSingletons();
2.if (singletonObject == null)
后续的步骤其实就是判断是否为原型bean或者是其他作用域的的bean
存入三级缓存如果earlySingletonExposure判断为true,则进入addSingletonFactory方法
创建bean:createBean
return wrappedBean;
此时传进来的singletonFactory实例方法是createBean,内部会重写getObject();方法!等singletonFactory完成后才进行对应的getObject();
初始化内部会判断你是否有被提前调用后置处理器
createBean
createBeanInstance 顾名思义就是创建一个实例
上来加锁后,就先获取一级缓存,第一次是获取不到的!
1.第一次调用getSingleton(beanName);
难点理解:if (this.earlyProxyReferences.remove(cacheKey) != bean)①.initializeBean初始化时,传入的bean是原始bean;②当初始化执行到判断是否被提前代理这一步时会进行判断:1.如果被提前代理了:cacheKey取出来的就是原始bean;2.如果没有被提前代理:cacheKey取出来就是null;所以:当传进来的原始bean和这时候取出来的bean进行比较时,就可以确定是否被提前引用了!▲也就是说当循环引用触发了getObject方法后,就会将原始bean缓存起来,然后这个被缓存起来的原始bean就是一个标识!
判断是否被提前代理!
判断当前实例化的bean是否正在销毁的集合里面,如果在销毁中就会抛出异常,不会再往下走!
返回的bean可能是传进去时的原始bean(就是什么样子进去就什么样子出来,没有发生改变),也可能是因为动态代理的bean;注:如果传出来是动态代理的bean就证明没有被提前触发!
调用初始化后置处理器!
4.singletonObject = singletonFactory.getObject();
开头通过beanName获取bean实例,如果获取到的实例不满足条件,就会调用核心代码getBean(beanName);
▲也就是出现了常规情况下无法解决的循环依赖问题!
当三级缓存转二级缓存时,会提前触发AOP代理
1.Spring容器核心创建方法refresh()
doGetBean方法很重要,内容有很多!
doCreateBean
singletonFactory就是由createBean创建出来的(亏A特)
判断:第一步.如果二级缓存earlySingletonReference不为null时进入第二步;第二步.exposedObject == bean;==》意思为初始化返回的bean和原始的bean相同!意思就是初始化时没bean没有发生改变,注:此处没发生改变的原因有两种:1.后置处理器被提前执行过了2.因为没有写AOP等切面,将bean原本返回了;(当然,不过是第一还是第二种,都会顺利执行第三步)这进入第三步第三步.exposedObject = earlySingletonReference;就是将二级缓存的引用,改成当前引用!
打标记!(标记为创建中)这部分是先判断并把需要创建的bean打上正在创建标记,把BeanDefinition里存储的依赖bean挨个取出来进行实例化
Object wrappedBean = bean;
doGetBean
判断该bean的class是否存在,也就是该bean是可以通过class创建的
AbstractBeanFactory abf = new AbstractBeanFactory();
3.markBeanAsCreated(beanName);
beanFactory.preInstantiateSingletons();
如果第二步判断二级缓存earlySingletonReference为null;
第二次getSingleton真正创建整个bean
先加锁,然后判断singletonObject即:一级缓存是否存在!
尝试获取bean这部分是通过getSingleton(beanName)方法去singleton缓存中找bean实例,应该是拿不到的,因为我们是第一次初始化,缓存中肯定不存在。
getBean(beanName);
String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
populateBean这个方法可谓大名鼎鼎,主要就是完成属性注入,也就是大家常常说的自动注入;假设本文环境中的代码运行完这行代码那么则会注入y,而y又引用了x,所以注入进来的y对象,也完成了x的注入;
3.添加到第三级缓存,修改getObjectspan style=\"font-size: inherit;\
3.beforeSingletonCreation(beanName);
true
第一次getSingleton只是尝试获取bean
准备方法重写
2.getParentBeanFactory();
将返回的结果exposedObject进行判断
getSingletion大致步骤
addSingletonFactory方法内部调用earlyProxyReferences(singletonFactory)(提前曝光代理)
注: wrapIfNecessary方法返回的不一定是代理对象!内部会对对象进行判断,看看是否有些代理切面!有:则返回代理对象!没有:则返回原来的bean!(即当前bean)
获取二级缓存earlySingletonReference
将获取到的bean返回return bean;
然后将earlySingletonObjects二级缓存删除
if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference;} }
初始化前置处理器
1. Object singletonObject = this.singletonObjects.get(beanName);
第二步判断不相同时即:exposedObject != bean
就是看是否符合单例beanexposedObject:就是给earlySingletonExposure这个布尔类型的变量赋值;——这个变量的意义是——是否支持(开启了)循环依赖1.mbd.isSingleton():判断当前实例化的bean是否为单例; 2.this.allowCircularReferences:整个全局变量spring 默认为true;当然spring提供了api供程序员修改 3.isSingletonCurrentlyInCreation(beanName)):判断当前正在创建的bean是否在正在创建bean的集合当中;
doCreateBean也很重要,内部方法也很多循环依赖就在这个方法内部触发循环!!!
循环依赖开始BgetBean(beanName);
mbdToUse.prepareMethodOverrides();
判断当前正在实例化的bean是否存在正在创建的集合当中,
会尝试在各级缓存中获取bean,获取到了就会设置产生和初始化!
for循环遍历dependentBeans ==》然后add到actualDependentBeans里;检测依赖在Spring中解决循环依赖只对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常。在这个步骤里面会检测已经加载的bean是否已经出现了依赖循环,并判断是否需要抛出异常;
1.if (earlySingletonExposure)为true时
初始化后置处理器
beanPostProcessor是可以临时修改bean的,它的优先级高于正常实例化bean的(也就是后续实例化该bean的过程),如果beanPostProcessor能返回,则直接返回了
这段是根据当前的beanfactory获取父一级的beanfactory,然后逐级递归的查找我们需要的bean,很显然在这里依然获取不到我们的bean,原因同第一部分。
return exposedObject;
0.doGetBean
false
exposedObject初始化返回的exposedObject可能是代理对象,也可能是原始对象!
if (!actualDependentBeans.isEmpty())则抛出异常!表示存在循环依赖!
Spring
主要分析其中之一:finishBeanFactoryInitialization方法
2_1.判断成立后if (this.singletonsCurrentlyInDestruction)
if(earlySingletonExposure)如果是true则添加到三级缓存,同时重写getObject,如果为false就跳过直接下一步;
因为bean创建后其所依赖的bean一定是已经创建的。actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是存在循环依赖。
2.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
getBean(beanName)中的核心代码就是 doGetBean
判断是否为空,在spring 初始化bean的时候这里肯定为空,故而成立
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName))
支持(开启了)循环依赖earlySingletonExposure
收藏
0 条评论
下一页