spring初始化过程的分析这里不再赘述,可参考另外一篇https://www.cnblogs.com/reboot30/p/8505664.html
我们这里从org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean直接开始,如果从三级缓存能够获取到bean的话,就直接返回bean,
在getSingleton中将bean从三级缓存升级到二级缓存,这点在后面非常有用, 创建bean的时候会根据二级缓存中有没有bean实例判断是否该bean在创建过程中被
别人引用了。
如果从一、二、三级缓存均未获取到bean,进入创建bean过程:
图1-1:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) {
// 检查一级缓存是否存在该bean Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean ‘" + beanName + "‘"); }
// 将bean放入singletonsCurrentlyInCreation beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try {
// 调用入参singletonFactory创建bean singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; }
// 将beanName从singletonsCurrentlyInCreation移除 afterSingletonCreation(beanName); } if (newSingleton) {
// 创建成功,将bean升级到一级缓存 addSingleton(beanName, singletonObject); } } return singletonObject; } }
回到图1-1,第二个入参为函数接口org.springframework.beans.factory.ObjectFactory,实际调用子类如下方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
最终调用doCreateBean创建bean:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean核心代码片段如下图一一列出:
总体步骤为:
1.创建实例
2.将刚创建的早期bean放入三级缓存
从三级缓存获取bean时,实际是通过org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference方法返回bean,这里要注意,返回的bean有可能是经过SmartInstantiationAwareBeanPostProcessor处理过的。
3.populateBean、initializeBean
4.如果暴露了早期bean,就从一、二级缓存获取bean,目的是判断是否有被循环依赖。
5.如果步骤4获取到了就比较早期暴露出去的bean和initializeBean之后的bean是否是同一个:
如果是,说明早期bean A从暴露出去之后没有发生变化,直接返回4中获取的bean,为什么?
因为populateBean的时候如果注入的bean B循环引用了bean A,那么会在一开始的org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean处将bean A从三级缓存上升到二级缓存,由上面分析我们知道,三级缓存存放的是ObjectFactory,getObject实际调用的是org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference,这个里面有可能改变原始bean,所以,当initializeBean前后还是同一个对象时,以缓存中的bean为主。
如果不是,说明initializeBean内部改变了早期bean,比如某个beanPostProcessor给bean创建了代理,这个时候就存在问题了,因为早期bean被暴露出去给别的bean使用了,存在一致性问题,这个时候就会抛出BeanCurrentlyInCreationException异常。
原文:https://www.cnblogs.com/reboot30/p/14684648.html