参考源

https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click

https://www.bilibili.com/video/BV12Z4y197MU?spm_id_from=333.999.0.0

《Spring源码深度解析(第2版)》

版本

本文章基于 Spring 5.3.15


Bean 的生命周期示意图(存在循环依赖和 AOP)

执行创建 Bean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException

AbstractAutowireCapableBeanFactory

  1. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
  2. // 实例化 Bean
  3. BeanWrapper instanceWrapper = null;
  4. // 是否为单例
  5. if (mbd.isSingleton()) {
  6. // 有可能在本 Bean 创建之前
  7. // 就有其他 Bean 把当前 Bean 给创建出来了(比如依赖注入过程中)
  8. // 所以这里先将其删除
  9. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  10. }
  11. if (instanceWrapper == null) {
  12. // 创建 Bean 实例
  13. // 根据指定 bean 使用对应的策略创建新的实例
  14. // 如:工厂方法、构造函数自动注入、简单初始化
  15. instanceWrapper = createBeanInstance(beanName, mbd, args);
  16. }
  17. // 获得 Bean 对象
  18. Object bean = instanceWrapper.getWrappedInstance();
  19. Class<?> beanType = instanceWrapper.getWrappedClass();
  20. if (beanType != NullBean.class) {
  21. mbd.resolvedTargetType = beanType;
  22. }
  23. // 后置处理合并的 BeanDefinition
  24. synchronized (mbd.postProcessingLock) {
  25. if (!mbd.postProcessed) {
  26. try {
  27. // 应用 MergedBeanDefinitionPostProcessors
  28. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  29. } catch (Throwable ex) {
  30. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex);
  31. }
  32. mbd.postProcessed = true;
  33. }
  34. }
  35. // 是否提前暴露
  36. // 为了解决循环依赖提早缓存单例创建工厂
  37. // 是否需要提早曝光:单例 & 允许循环依赖 & 当前 bean 正在创建中
  38. // 用于检测循环依赖
  39. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
  40. if (earlySingletonExposure) {
  41. if (logger.isTraceEnabled()) {
  42. logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
  43. }
  44. // 添加到三级缓存
  45. // 为避免后期循环依赖,可以在 bean 初始化完成前将创建实例的 ObjectFactory 加入工厂
  46. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  47. }
  48. Object exposedObject = bean;
  49. try {
  50. // 属性填充
  51. // 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性,则会递归初始依赖 bean
  52. populateBean(beanName, mbd, instanceWrapper);
  53. // 初始化
  54. // 调用初始化方法,比如 init-method
  55. exposedObject = initializeBean(beanName, exposedObject, mbd);
  56. } catch (Throwable ex) {
  57. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  58. throw (BeanCreationException) ex;
  59. } else {
  60. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  61. }
  62. }
  63. if (earlySingletonExposure) {
  64. // 获取单例对象
  65. Object earlySingletonReference = getSingleton(beanName, false);
  66. // 在检测到有循环依赖的情况下才会不为空
  67. if (earlySingletonReference != null) {
  68. // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
  69. if (exposedObject == bean) {
  70. exposedObject = earlySingletonReference;
  71. } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  72. String[] dependentBeans = getDependentBeans(beanName);
  73. Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
  74. for (String dependentBean : dependentBeans) {
  75. // 检测依赖
  76. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  77. actualDependentBeans.add(dependentBean);
  78. }
  79. }
  80. // 因为 bean 创建后其所依赖的 bean 一定是已经创建的
  81. // actualDependentBeans 不为空则表示当前bean 创建后其依赖的 bean 却没有全部创建完,也就是说存在循环依赖
  82. if (!actualDependentBeans.isEmpty()) {
  83. throw new BeanCurrentlyInCreationException(beanName,
  84. "Bean with name '" + beanName + "' has been injected into other beans [" +
  85. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  86. "] in its raw version as part of a circular reference, but has eventually been " +
  87. "wrapped. This means that said other beans do not use the final version of the " +
  88. "bean. This is often the result of over-eager type matching - consider using " +
  89. "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
  90. }
  91. }
  92. }
  93. }
  94. try {
  95. // 根据 scope 注册 bean
  96. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  97. } catch (BeanDefinitionValidationException ex) {
  98. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  99. }
  100. return exposedObject;
  101. }

实例化

创建 Bean 实例

根据指定 bean 使用对应的策略创建新的实例

如:工厂方法、构造函数自动注入、简单初始化

createBeanInstance(beanName, mbd, args)

AbstractAutowireCapableBeanFactory

  1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
  2. // 解析 class
  3. Class<?> beanClass = resolveBeanClass(mbd, beanName);
  4. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
  5. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
  6. }
  7. Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
  8. if (instanceSupplier != null) {
  9. return obtainFromSupplier(instanceSupplier, beanName);
  10. }
  11. // 如果工厂方法不为空则使用工厂方法初始化策略
  12. if (mbd.getFactoryMethodName() != null) {
  13. return instantiateUsingFactoryMethod(beanName, mbd, args);
  14. }
  15. boolean resolved = false;
  16. boolean autowireNecessary = false;
  17. if (args == null) {
  18. synchronized (mbd.constructorArgumentLock) {
  19. // 一个类有多个构造函数,每个构造函数都有不同的参数, 所以调用前需要先根据参数锁定构造函数或对应的工厂方法
  20. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  21. resolved = true;
  22. autowireNecessary = mbd.constructorArgumentsResolved;
  23. }
  24. }
  25. }
  26. // 如果已经解析过则使用解析好的构造函数方法不需要再次锁定
  27. if (resolved) {
  28. // 构造函数自动注入
  29. if (autowireNecessary) {
  30. return autowireConstructor(beanName, mbd, null, null);
  31. }
  32. // 使用默认构造函数构造
  33. else {
  34. return instantiateBean(beanName, mbd);
  35. }
  36. }
  37. // 需要根据参数解析构造函数
  38. Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  39. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
  40. // 构造函数自动注入
  41. return autowireConstructor(beanName, mbd, ctors, args);
  42. }
  43. ctors = mbd.getPreferredConstructors();
  44. if (ctors != null) {
  45. return autowireConstructor(beanName, mbd, ctors, null);
  46. }
  47. // 使用默认构造函数构造
  48. return instantiateBean(beanName, mbd);
  49. }

是否提早暴露

是否提前暴露

为了解决循环依赖提早缓存单例创建工厂

是否需要提早曝光:单例 & 允许循环依赖 & 当前 bean 正在创建中

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName))

DefaultSingletonBeanRegistry

  1. /**
  2. * 单例是否正在创建中
  3. */
  4. private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
  5. public boolean isSingletonCurrentlyInCreation(String beanName) {
  6. return this.singletonsCurrentlyInCreation.contains(beanName);
  7. }

添加到三级缓存

添加到三级缓存

为避免后期循环依赖,可以在 bean 初始化完成前将创建实例的 ObjectFactory 加入工厂

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))

DefaultSingletonBeanRegistry

  1. // 一级缓存:也叫单例池。
  2. // 用于保存 BeanName 和创建 bean 实例之间的关系,bean name -> bean instance
  3. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  4. // 二级缓存:存放提前AOP生成的代理对象,保持代理对象的单例。
  5. private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  6. // 三级缓存:存放用于生成代理对象的Lambda,用于循环依赖中生成代理对象,以打破循环依赖。
  7. // 用于保存 BeanName 和创建 bean 的工厂之间的关系,bean name -> ObjectFactory
  8. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  9. // 用来保存当前所有已注册的 bean
  10. private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
  11. protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  12. Assert.notNull(singletonFactory, "Singleton factory must not be null");
  13. // 为了保持操作的原子性,加锁
  14. synchronized (this.singletonObjects) {
  15. // 单例池中是否存在
  16. if (!this.singletonObjects.containsKey(beanName)) {
  17. // 对应记录放人三级缓存
  18. this.singletonFactories.put(beanName, singletonFactory);
  19. // 二级缓存移除对应记录
  20. this.earlySingletonObjects.remove(beanName);
  21. // 添加到已注册的 Bean
  22. this.registeredSingletons.add(beanName);
  23. }
  24. }
  25. }

获取单例对象

获取单例对象

getSingleton(beanName, false)

DefaultSingletonBeanRegistry

  1. // 一级缓存:也叫单例池。
  2. // 用于保存 BeanName 和创建 bean 实例之间的关系,bean name -> bean instance
  3. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  4. // 二级缓存:存放提前AOP生成的代理对象,保持代理对象的单例。
  5. private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  6. // 三级缓存:存放用于生成代理对象的Lambda,用于循环依赖中生成代理对象,以打破循环依赖。
  7. // 用于保存 BeanName 和创建 bean 的工厂之间的关系,bean name -> ObjectFactory
  8. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  9. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  10. // 检查单例池中是否存在实例
  11. Object singletonObject = this.singletonObjects.get(beanName);
  12. // 想要获取的 Bean 正在创建中,说明出现了循环依赖
  13. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  14. // 从二级缓存中获取该 Bean 的代理对象
  15. singletonObject = this.earlySingletonObjects.get(beanName);
  16. if (singletonObject == null && allowEarlyReference) {
  17. // 如果二级缓存没有,则锁定单例池并进行处理
  18. synchronized (this.singletonObjects) {
  19. // 检查单例池中是否存在实例
  20. singletonObject = this.singletonObjects.get(beanName);
  21. if (singletonObject == null) {
  22. // 从二级缓存中获取该 Bean 的代理对象
  23. singletonObject = this.earlySingletonObjects.get(beanName);
  24. if (singletonObject == null) {
  25. // 当某些方法需要提前初始化的时候则会调用 addSingletonFactory 方法将对应的 ObjectFactory 初始化策略存储在三级缓存中
  26. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  27. // 从三级缓存中找到了
  28. if (singletonFactory != null) {
  29. // 调用预先设定的 getObject 方法
  30. // 这里会执行 Lambda 表达式
  31. singletonObject = singletonFactory.getObject();
  32. // 记录在二级缓存中,删除三级缓存对应记录
  33. // 二级缓存和三级缓存互斥
  34. this.earlySingletonObjects.put(beanName, singletonObject);
  35. this.singletonFactories.remove(beanName);
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }
  42. return singletonObject;
  43. }

提前 AOP

提前 AOP 就是三级缓存中存放的 Lambda 表达式执行的方法

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))

AbstractAutowireCapableBeanFactory

  1. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  2. Object exposedObject = bean;
  3. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  4. for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
  5. // 提前 AOP
  6. exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
  7. }
  8. }
  9. return exposedObject;
  10. }

提前 AOP

getEarlyBeanReference(exposedObject, beanName)

AbstractAutoProxyCreator

  1. public Object getEarlyBeanReference(Object bean, String beanName) {
  2. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  3. // 早期进行 AOP,则将标识传入
  4. // 供后面再进行 AOP 时进行判断
  5. this.earlyProxyReferences.put(cacheKey, bean);
  6. // 必要时填充
  7. return wrapIfNecessary(bean, beanName, cacheKey);
  8. }

正常 AOP

初始化

initializeBean(beanName, exposedObject, mbd)

AbstractAutowireCapableBeanFactory

  1. protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  2. if (System.getSecurityManager() != null) {
  3. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  4. invokeAwareMethods(beanName, bean);
  5. return null;
  6. }, getAccessControlContext());
  7. } else {
  8. // 对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
  9. invokeAwareMethods(beanName, bean);
  10. }
  11. Object wrappedBean = bean;
  12. if (mbd == null || !mbd.isSynthetic()) {
  13. // 初始化前
  14. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  15. }
  16. try {
  17. // 激活用户自定义的 init 方法
  18. invokeInitMethods(beanName, wrappedBean, mbd);
  19. } catch (Throwable ex) {
  20. throw new BeanCreationException(
  21. (mbd != null ? mbd.getResourceDescription() : null),
  22. beanName, "Invocation of init method failed", ex);
  23. }
  24. if (mbd == null || !mbd.isSynthetic()) {
  25. // 初始化后
  26. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  27. }
  28. return wrappedBean;
  29. }

初始化后

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)

AbstractAutowireCapableBeanFactory

  1. public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
  2. Object result = existingBean;
  3. for (BeanPostProcessor processor : getBeanPostProcessors()) {
  4. // 初始化后的后处理
  5. Object current = processor.postProcessAfterInitialization(result, beanName);
  6. if (current == null) {
  7. return result;
  8. }
  9. result = current;
  10. }
  11. return result;
  12. }

初始化后的后处理

postProcessAfterInitialization(result, beanName)

AbstractAutoProxyCreator

  1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  2. if (bean != null) {
  3. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  4. // 如果前面没有进行过 AOP,这里进行 AOP
  5. // 如果前面进行过 AOP,删除对应记录,这里不进行 AOP
  6. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  7. return wrapIfNecessary(bean, beanName, cacheKey);
  8. }
  9. }
  10. return bean;
  11. }

Spring源码 21 Bean生命周期的更多相关文章

  1. Spring源码系列 — Bean生命周期

    前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...

  2. Spring源码之Bean生命周期

    https://www.jianshu.com/p/1dec08d290c1 https://www.cnblogs.com/zrtqsk/p/3735273.html 总结 将class文件加载成B ...

  3. Spring之BeanFactory及Bean生命周期

    1.spring通过BeanFactory灵活配置.管理bean,Spring对管理的bean没有任何特别的要求,完全支持对POJO的管理: 2.BeanFactory有个ApplicationCon ...

  4. 深入源码理解SpringBean生命周期

    概述 本文描述下Spring的实例化.初始化.销毁,整个SpringBean生命周期,聊一聊BeanPostProcessor的回调时机.Aware方法的回调时机.初始化方法的回调及其顺序.销毁方法的 ...

  5. Vue2.0源码阅读笔记--生命周期

    一.Vue2.0的生命周期 Vue2.0的整个生命周期有八个:分别是 1.beforeCreate,2.created,3.beforeMount,4.mounted,5.beforeUpdate,6 ...

  6. Laravel源码分析--Laravel生命周期详解

    一.XDEBUG调试 这里我们需要用到php的 xdebug 拓展,所以需要小伙伴们自己去装一下,因为我这里用的是docker,所以就简单介绍下在docker中使用xdebug的注意点. 1.在php ...

  7. angular11源码探索[DoCheck 生命周期和onChanges区别]

    网站 https://blog.thoughtram.io/ https://juristr.com/ https://www.concretepage.com/angular/ https://ww ...

  8. Spring BeanFactory 初始化 和 Bean 生命周期

    (version:spring-context-4.3.15.RELEASE) AbstractApplicationContext#refresh() public void refresh() t ...

  9. 【spring源码】bean的实例化(转载)

    首先来看一段代码,看过上一节的朋友肯定对这段代码并不陌生.这一段代码诠释了Spring加载bean的完整过程,包括读取配置文件,扫描包,加载类,实例化bean,注入bean属性依赖. 上一节介绍了Sp ...

随机推荐

  1. .Net分表分库动态化处理

    介绍 本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业务代码入侵 背景 最近有个小伙伴来问我,分表下他有一批数据,这个 ...

  2. 使用pip安装库或执行pip命令时报错解决方案

    初次安装pip后执行安装升级一般不会有问题,但是国外的镜像源下载升级由于网速过慢会进行报错,提示需要升级 pip 或者下载速度很慢最后直接报了错如下图: 这个时候只需要修改镜像源即可,建议修改为永久镜 ...

  3. SpringCloudAlibaba分布式流量控制组件Sentinel实战与源码分析(上)

    概述 定义 Sentinel官网地址 https://sentinelguard.io/zh-cn/index.html 最新版本v1.8.4 Sentinel官网文档地址 https://senti ...

  4. 开源项目 PM 浅谈如何设计官网

      有用户反馈进入官网首页光秃秃的一片,大家忙着做产品,忽略了官网的建设,惭愧惭愧.   确实,极简风格和极其简单还是有很大区别的.     旧的 Web 端   除了极其简单之外,它还有一个小问题, ...

  5. 【2022-06-16】Python解释器的下载安装与使用

    一.Python解释器介绍 什么是Python解释器? Python是一门解释型语言,解释器是Python运行必不可少的一种工具.所以,我们搭建Python环境,本质上就是对Python进行配置和定制 ...

  6. 记一次 .NET 某工控数据采集平台 线程数 爆高分析

    一:背景 1. 讲故事 前几天有位朋友在 B站 加到我,说他的程序出现了 线程数 爆高的问题,让我帮忙看一下怎么回事,截图如下: 说来也奇怪,这些天碰到了好几起关于线程数无缘无故的爆高,不过那几个问题 ...

  7. docker下node环境搭建

    初始化⼀个NodeJs程序 以下操作必须已经安装了NodeJS. ⾸先创建⼀个空⽂件夹.并创建以下⽂件: server.js package.json Dockerfile .dockerignore ...

  8. 官宣!微软发布 VS Code Server!

    北京时间 2022 年 7 月 7 日,微软在 VS Code 官方博客中宣布了 Visual Studio Code Server! 远程开发的过去与未来 2019 年,微软发布了 VS Code ...

  9. javaScript去重的11种方法

    前言 去重是开发和面试中经常遇到的问题,下面是总结的 11 种去重方法 方法 示例数组 var arr = [1, 2, 4, 5, 5, 2, 1, 1, 4, 6] set + 解构赋值 这种方法 ...

  10. springboot java -jar指定启动的jar外部配置文件

    Limited Setting Effect 中文描述 Java 8 -Xbootclasspath:<path> Sets the search path for bootstrap c ...