单例Bean的创建流程
创始人
2024-06-03 12:29:38
0

简要介绍

bean的创建,需要经过查找,创建,注入,实例化三阶段

finishBeanFactoryInitialization

前言提到,refresh方法执行了finishBeanFactoryInitialization,这个方法便是完成了bean的创建与初始化。
每一个最后都会走向doGetBean

doGetBean

doGetBean是用于返回bean的方法,如果bean不存在,还会调用其内部的doCreateBean完成bean的创建

protected  T doGetBean(final String name, @Nullable final Class requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {final String beanName = transformedBeanName(name);Object bean;// 从缓存池中获取Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {//如果存在,判断一下是否还在创建,都已经创建但是状态却是还在创建当然是错的。然后判断一下if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}//这是为了防止beanFactory套用beanFactory,这里提供了递归使用getObject方法,从而获取最终beanbean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// 空的,要不是没创建过的单例bean,要不是原型bean,并且这个bean一定不能是if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 打上已经创建的标记,防止对象反复创建if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// 优先完成@DependOn注解指定的类的bean的创建与获取String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// 这里面实际上就是增加这个bean依赖了哪个bean,和哪个被依赖的bean被这个bean依赖的双重引用registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// 如果是单例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});// 也是递归向里调用,直到返回的不是factoryBeanbean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");}final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// 检查一下是否需要格式转换,比如XML的字符串转化为对象的类型if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;
}

试图直接返回

这是singletonObject的逻辑,如果一级有,直接返回,如果一级没有,那么就可能涉及修改操作,所以提前完成上锁。为什么锁的是一级缓存而不是二级缓存呢,正是因为三级缓存在完成调用之后会将对象加入二级缓存,然后其它有着相同需求正在等待的线程就可以直接从二级缓存取出对象,而不需要双重检验机制了。
然后进行二级和三级缓存的查找。如果是在三级缓存中找到的,那么就会调用其中getObject方法,这个方法在单例中就是getReference方法

//三级缓存,保存工厂
private final Map> singletonFactories = new HashMap<>(16);
//二级缓存,保存工厂创建的对象
private final Map earlySingletonObjects = new HashMap<>(16);
//一级缓存,保存所有完成创建的对象
private final Map singletonObjects = new ConcurrentHashMap<>(256);protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;
}

doCreateBean方法的“AOP”

以下对源码的验证部分进行大量删除,只剩下主干
这个方法在调用doCreateBean之前,会将其加入一个set表示正在创建,在调用doCreateBean正常结束之后会将其删除,并完成一级缓存的添加和二三级缓存的清除

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {// 添加进入singletonsCurrentlyInCreation,表示是正在创建的单例对象beforeSingletonCreation(beanName);boolean newSingleton = false;try {//这里才是真正调用了 doCreateBeansingletonObject = singletonFactory.getObject();// 如果走到这里说明初始化成功了newSingleton = true;} finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}// 从singletonsCurrentlyInCreation中移除afterSingletonCreation(beanName);}// 如果初始化成功了,那么加入一级缓存if (newSingleton) {addSingleton(beanName, singletonObject);}}return singletonObject;}
}protected void addSingleton(String beanName, Object singletonObject) {// 将这个对象加入一级缓存,从二三级删除,并标记为已经注册synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}
}

doCreateBean的实体

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// 实例化beanif (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();Class beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// 可以理解为走了一个beanPostProcessorssynchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);mbd.postProcessed = true;}}// 如果设置了属性,并且是正在创建的单例bean,就会添加单例工厂.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;// 注入属性populateBean(beanName, mbd, instanceWrapper);// 初始化beanexposedObject = initializeBean(beanName, exposedObject, mbd);// 如果支持循环引用,并且存在该对象,这是为了保证返回的一定是代理对象if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}}}// 如果需要回调destory方法,会放入destroybeans,这样在销毁的时候就会从destroybeans剔除并回调registerDisposableBeanIfNecessary(beanName, bean, mbd);return exposedObject;
}

关联的属性这时候注入

属性注入的时候对Autowire注解进行了注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}// 使用AutowiredAnnotationBeanPostProcessor,将类中所有Autowired注解都提取出来,并在postProcessPropertyValues逐一完成注入for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}// 把property数组放入beanWrapper里面,便于后续使用if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}
}

对于三级缓存的解释

比如A包含B,B包含A的关系,用户尝试获取A。
一开始进入A的getBean,由于缓存中不存在A,所以进入A的create方法,会生成单例工厂,并将单例工厂放入三级缓存,然后进入属性注入环节,会尝试注入B,这时陷入B的getBean。
B会标记自己是正在生成,然后进入create方法,生成单例工厂,并将单例工厂放入三级缓存,然后进入属性注入环节,会尝试注入A,这时陷入A的getBean,这时会从三级缓存中取出A的单例工厂,并且调用其getEarlyReference方法,AbstractAutoProxyCreator会将A加入AOP缓存,然后生成代理对象,并将A移出三级缓存,将其注入二级缓存,然后返回给B使用。B获取到之后会继续完成属性注入和初始化代理,然后从三级缓存中删除自己,加入一级缓存,返回代理对象B给A。
A拿到了B的代理对象,会继续完成属性注入和初始化代理,在初始化代理时候,A会检查AOP缓存,由于A会在AOP缓存里发现自己,所以直接返回。在create方法的最后,A会从二级缓存中取出A的代理,然后从二级缓存中删除A,并加入一级缓存,将A的代理返回给用户。
假设更麻烦一些,B在获取A的时候,C也在获取A,会怎样呢。由于进入二级和三级缓存都有同一把锁,比如B先进入了这把锁,那么它会先检查二级缓存是否有A,发现没有,会进入三级缓存取出A的工厂,通过A的工厂完成A的代理,再将其放入二级缓存,然后释放锁,这是C才会获取到这把锁,它会在二级缓存直接发现了A,于是直接注入,这就是二级缓存的作用。

相关内容

热门资讯

安卓用的是什么系统,深度解析A... 你有没有想过,你的安卓手机里到底装的是什么系统呢?是不是觉得这个问题有点儿深奥,其实它背后隐藏着手机...
安卓系统如何改定位苹果,安卓系... 你有没有想过,你的安卓手机竟然可以模仿苹果的定位功能?没错,就是那种精准到让你仿佛置身于苹果用户世界...
安卓系统不能删除软件吗,为何无... 你是不是也遇到过这种情况:手机里装了好多软件,可就是找不到删除它们的办法?别急,今天就来聊聊这个让人...
鸿蒙系统属于安卓么,揭秘其与安... 你有没有想过,手机里的那个鸿蒙系统,它到底是不是安卓的“亲戚”呢?这个问题,估计不少手机控都在心里默...
安卓大屏导航恢复系统,重塑流畅... 你有没有发现,手机屏幕越来越大,导航系统也越来越复杂?有时候,我们不小心把安卓大屏导航恢复系统给误删...
国产安卓机哪个系统好用,探索好... 你有没有想过,国产安卓机哪个系统最好用呢?这可是个让人纠结的问题,毕竟每个系统都有它的特色和亮点。今...
安卓11系统操作方法,轻松上手... 你升级到安卓11系统了吗?是不是还在为如何更好地操作这个新系统而烦恼呢?别急,今天我就来给你详细介绍...
安卓2.3系统流畅内存,揭秘内... 你有没有想过,为什么有些老手机还能跑得飞快,而有些新手机却卡得要命?今天,咱们就来聊聊这个话题——安...
支持安卓系统的硬件芯片,引领智... 你有没有发现,现在手机的世界里,支持安卓系统的硬件芯片可是越来越厉害了呢!想象那些小小的芯片,就像魔...
手机安卓系统性价比,性能与价格... 你有没有发现,现在手机市场上安卓系统的手机越来越受欢迎了呢?这不,最近我入手了一款性价比超高的安卓手...
群晖vmm安装安卓系统,群晖V... 亲爱的电脑爱好者们,你是否曾梦想过在群晖NAS上安装安卓系统,享受移动设备的便捷与NAS的强大存储?...
免费的美发会员安卓系统,安卓系... 亲爱的读者们,你是否曾在街头巷尾,被那些免费的美发会员卡吸引得心痒痒?想象不用花一分钱,就能享受到专...
ego华为装安卓系统,开启智能... 你知道吗?最近科技圈可是炸开了锅,因为华为这个巨头竟然要给自家手机装上安卓系统!这可不是什么小打小闹...
安卓系统软件数据,揭秘智能设备... 你知道吗?在这个科技飞速发展的时代,安卓系统软件数据可是个让人又爱又恨的小家伙。它就像一个调皮的精灵...
安卓系统啥文档不能删,安卓系统... 你有没有想过,在你的安卓手机里,有些文档就像是顽皮的小精灵,无论你怎么赶,它们就是赖在那里不肯走呢?...
安卓游戏系统怎么转苹果,安卓游... 你是不是也和我一样,手里拿着安卓手机玩得乐不思蜀,突然有一天,发现了一款超级酷炫的苹果游戏,心痒痒地...
安卓能否刷华为系统版本,揭秘华... 你有没有想过,你的安卓手机能不能刷上华为的系统版本呢?这可是个让人好奇不已的话题呢!想象如果你的安卓...
谷歌最新系统安卓,谷歌带来的颠... 哇,你知道吗?最近谷歌又放大招了!他们推出了全新的操作系统——安卓!这可不是一个小小的更新,而是一次...
鸿蒙系统真的不算安卓吗,引领全... 最近手机圈子里可是热闹非凡呢!尤其是华为的鸿蒙系统,自从发布以来,就一直是大家讨论的焦点。有人说,鸿...
电脑整盘安装安卓系统 你有没有想过,你的电脑除了装Windows系统,还能来个变身大法,变成一个安卓小怪兽呢?没错,今天就...