读完这篇文章你将会收获到
Spring
何时将bean
加入到第三级缓存和第一级缓存中Spring
何时回调各种Aware
接口、BeanPostProcessor
、InitializingBean
等
相关文章
- Spring 获取单例流程(一)
- Spring 获取单例流程(二)
- Spring 循环依赖 (公众号内查看(同时发布无法获取到链接))
概述
上两篇文章 Spring 获取单例流程(一) 和 Spring 获取单例流程(二) 介绍了 getBean
前面的流程,今天最后的收尾,把后面的流程继续一起学习下
源码分析
// 我依赖的大哥都好了 // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // 从三级缓存中移除这个 beanName 因为它可能被放进去了 因为放进去三级缓存可以解决 setter 的循环依赖 destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } 复制代码
如果我们要创建的 bean
是一个单例,
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { // 看看第一级缓存中有没有 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { // 将 beanName 加入到 singletonsCurrentlyInCreation 中,代表它正在创建中 beforeSingletonCreation(beanName); boolean newSingleton = false; try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { throw ex; } catch (BeanCreationException ex) { throw ex; } finally { // singletonsCurrentlyInCreation 从这里面移除掉 afterSingletonCreation(beanName); } if (newSingleton) { // 加入缓存中 addSingleton(beanName, singletonObject); } } return singletonObject; } } 复制代码
删减了部分不重要的代码,我们大致来看看其流程
- 获取同步锁,然后判断第一级缓存是否已经存在这个
bean
了 - 如果不存在则将
beanName
加入到singletonsCurrentlyInCreation
中,代表它正在创建中 - 然后调用参数的
ObjectFactory
的getObject
方法获得一个bean
- 最后将其从
singletonsCurrentlyInCreation
中移除、代表其已经创建完成了 - 最后将其加入到第一级缓存中、从第二级和第三级缓存中移除掉
全篇完结.终 !!!
其实真正的秘密藏身在参数的 ObjectFactory
中,从上面的流程中可以宏观的知道 Spring
创建 bean
的一个流程
现在我们在看看参数的 ObjectFactory
究竟干啥子了
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ........... ........... try { // 真正 处理逻辑 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(xxxx); } } 复制代码
干活的还是 do
开头的大佬
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); } if (instanceWrapper == null) { // 根据指定 bean 使用对应的策略创建新的实例、如工厂方法、构造函数自动注入、简单初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); .......... ......... // 是否需要提前曝光、用来解决循环依赖的问题 // 是单例&允许循环依赖&正在创建中 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // 为了避免后期循环依赖、可以在 bean 初始化前将创建实例的ObjectFactory 加入工厂 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 填充属性 populateBean(beanName, mbd, instanceWrapper); // 调用初始方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { ......... } ........ ....... return exposedObject; } 复制代码
上面的流程大致就是
createBeanInstance
这个方法根据你的配置以及你的bean
的情况选择出一种创建bean
的方法、可能是工厂方法、可能是某个构造函数、可能是默认的构造函数。这里包含了当一个构造函数的参数是另一个bean
的时候、它会通过getBean
的方法获取这个参数的bean
- 然后将创建好的
bean
加入到第三级缓存中,默认设置我们是允许循环依赖的 populateBean
方法就是我们填充属性了、如果你依赖的其他Spring
的其他bean
是通过这种方式注入的话(autowireByName
autowireByType
)、就是在这一步注入的了,他获取其他bean
也是通过getBean
的方式获取
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ......... ......... if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } ......... ......... } 复制代码
initializeBean
则是调用我们的各种回调接口、Aware
类型的、BeanPostProcessor
、InitializingBean
、自定义初始化函数
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> {。 // 调用各种 Aware 接口 invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 调用各种 Aware 接口 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 调用 BeanPostProcessor postProcessBeforeInitialization wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 调用 InitializingBean 、自定义的初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // 调用 BeanPostProcessor postProcessAfterInitialization wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } 复制代码
- 其实整体的流程就差不多了
总结
- 根据参数中的
name
找出对应的beanName
、无论这个name
是别名或者是一个factoryBean
的beanName
- 查看缓存中是否包含这个
beanName
对象
- 先从一级缓存
singletonObjects
中看看有没有 - 然后从二级缓存
earlySingletonObjects
- 都没有的话再从三级缓存
singletonFactories
中看看有没有
- 如果缓存中有
bean
、那么我们还是需要处理一下这个bean
- 如果
Spring
缓存中返回的bean
是factoryBean
、而用户也想要的是一个beanFactory
(参数name
中的前缀是&
)、那么我们直接返回 - 如果
Spring
缓存中返回的bean
是普通的bean
、而用户也想要的是一个普通的bean
、那么就直接返回 - 如果
Spring
缓存中返回的bean
是一个factoryBean
、而用户想要的是一个普通的bean
、那么我们就要从factoryBean
中获取这个bean
- 而从
factoryBean
中获取这个bean
的过程中、需要调用到前置处理、后置处理和我们常用的接口回调BeanPostProcessor
- 如果缓存中没有
bean
、则判断是否是prototype
类型并且循环依赖 - 如果没有则尝试能否在父容器中找到该
bean
- 如果父容器也没有则获取该
beanName
对应的beanDefinition
找出其依赖的beanName
- 判断该
beanName
与 依赖的beanName
是否循环依赖、没有则注册其依赖关系并调用getBean
方法去创建依赖的beanName
- 将
beanName
加入到singletonsCurrentlyInCreation
中 - 根据指定 bean 使用对应的策略创建新的实例、如工厂方法、构造函数、创建一个不完整的 bean
- 将创建好的 bean 加入到第三级缓存中
- 进行属性填充、进行各种接口回调
- 最后将其从
singletonsCurrentlyInCreation
中移除、代表其已经创建完成了 - 最后将其加入到第一级缓存中、从第二级和第三级缓存中移除掉
- 返回
bean
给调用方