回顾一下前面,在**AbstractApplicationContext**中,**refresh()**完成了整个IOC容器的刷新,上回我们分析到了初始化剩下所有的单实例bean,这里面有几个核心的地方,**getBean(),createBean(),populateBean()**,三级缓存与循环依赖,完成这些后,整个IOC容器的大体流程就分析完了。本篇我们来分析Spring的**getBean()**

1.初始化所有的单实例bean对象

**finishBeanFactoryInitialization()**

  1. protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  2. // 为此上下文初始化转换服务
  3. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
  4. beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
  5. beanFactory.setConversionService(
  6. beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
  7. }
  8. // 如果容器里面没有字符串转换器,初始化一个字符串转换器放到容器中。
  9. if (!beanFactory.hasEmbeddedValueResolver()) {
  10. beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
  11. }
  12. // 尽早初始化LoadTimeWeaverAware beans,以便尽早注册它们的转换器。
  13. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  14. for (String weaverAwareName : weaverAwareNames) {
  15. getBean(weaverAwareName);
  16. }
  17. // 停止使用临时类加载器进行类型匹配
  18. beanFactory.setTempClassLoader(null);
  19. // 允许缓存所有bean定义元数据,不期望进一步的更改,冻结bd信息,冻结之后就无法往bf注册bd了
  20. beanFactory.freezeConfiguration();
  21. // 实例化所有剩余的单实例bean
  22. beanFactory.preInstantiateSingletons();
  23. }

冻结bd的信息实际上就是通过一个状态位来控制的,这里面最核心的一个方法或者说步骤就是实例化所有剩余的单实例bean对象。**beanFactory.preInstantiateSingletons()**

2.preInstantiateSingletons()

  1. @Override
  2. public void preInstantiateSingletons() throws BeansException {
  3. //日志打印
  4. if (logger.isTraceEnabled()) {
  5. logger.trace("Pre-instantiating singletons in " + this);
  6. }
  7. /*拿过来所有的beanDefinition names 信息*/
  8. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  9. // 触发所有的非懒加载的单例bean的初始化
  10. for (String beanName : beanNames) {
  11. //获取bean的定义信息
  12. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
  13. // bean不是抽象的 是单例的 不是懒加载的
  14. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
  15. //如果是工厂bean
  16. if (isFactoryBean(beanName)) {
  17. //通过getBean方法获取bean 前缀 & 拿到的是工厂bean
  18. Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
  19. //如果拿到的bean确定是工厂bean
  20. if (bean instanceof FactoryBean) {
  21. FactoryBean<?> factory = (FactoryBean<?>) bean;
  22. //判断这个工厂bean是否期望被初始化
  23. /*判断逻辑:SmartFactoryBean里面有一个isEagerInit方法,这个方法为true就表示这个工厂bean是需要现在创建的*/
  24. boolean isEagerInit = (factory instanceof SmartFactoryBean &&
  25. ((SmartFactoryBean<?>) factory).isEagerInit());
  26. //如果期望被初始化
  27. if (isEagerInit) {
  28. //通过getBean走创建bean的逻辑
  29. getBean(beanName);
  30. }
  31. }
  32. }
  33. else {//执行到这里,说明就是普通的单实例bean,不是工厂bean,直接通过getBean创建bean
  34. //三级缓存解决循环依赖的入口:
  35. /**
  36. * 重点
  37. */
  38. /**
  39. * eg:man 和 women 产生循环依赖
  40. * 1.第一次来到这里是首先去创建man
  41. */
  42. getBean(beanName);
  43. }
  44. }
  45. }
  46. // 触发所有的单实例bean的初始化后的回调逻辑
  47. for (String beanName : beanNames) {
  48. //从一级缓存获取单实例bean
  49. Object singletonInstance = getSingleton(beanName);
  50. //类型断言,执行回调
  51. /*SmartInitializingSingleton里面有一个方法 afterSingletonsInstantiated 这个方法需要在创建好单实例bean之后调用一下*/
  52. if (singletonInstance instanceof SmartInitializingSingleton) {
  53. StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
  54. .tag("beanName", beanName);
  55. SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
  56. //这里就是触发初始化后的回调逻辑
  57. smartSingleton.afterSingletonsInstantiated();
  58. smartInitialize.end();
  59. }
  60. }
  61. }

这里拿到所有的**beanDefinition**的名字,然后循环判断:【不是抽象的,单实例的,非懒加载的】,然后根据拿到的bean定义信息,再分为**FactoryBean****Bean**两种情况进行处理。

梳理一下这里的重点逻辑:

  1. 合并**beanDefinition**信息 **getMergedLocalBeanDefinition(beanName)**
  2. 获取bean对象 **getBean() **
  3. **SmartInitializingSingleton**回调**afterSingletonsInstantiated() **触发单实例bean初始化后的回调逻辑


接下来先来分析,如何合并bean的定义信息。

3. getMergedLocalBeanDefinition(beanName)

  1. protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
  2. // Quick check on the concurrent map first, with minimal locking.
  3. /*从缓存获取*/
  4. RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
  5. /*缓存有,直接返回*/
  6. if (mbd != null && !mbd.stale) {
  7. return mbd;
  8. }
  9. /*真正的合并 bd 的逻辑*/
  10. return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
  11. }

首先会先尝试从缓存来获取**beanDefinition**的信息,如果缓存有,就直接返回,否则就要触发合并bd的逻辑。

  1. protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
  2. throws BeanDefinitionStoreException {
  3. return getMergedBeanDefinition(beanName, bd, null);
  4. }
  1. protected RootBeanDefinition getMergedBeanDefinition(
  2. String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
  3. throws BeanDefinitionStoreException {
  4. synchronized (this.mergedBeanDefinitions) {
  5. /*合并后的bd信息
  6. * */
  7. RootBeanDefinition mbd = null;
  8. /*表示当前beanname对应的过期的mbd信息*/
  9. RootBeanDefinition previous = null;
  10. // Check with full lock now in order to enforce the same merged instance.
  11. /*null==null*/
  12. if (containingBd == null) {
  13. /*从缓存拿信息*/
  14. mbd = this.mergedBeanDefinitions.get(beanName);
  15. }
  16. /*条件成立说明mbd==null或者 过期...*/
  17. if (mbd == null || mbd.stale) {
  18. /*表示当前beanname对应的过期的mbd信息*/
  19. previous = mbd;
  20. /*没有当前beanName 对应的 bd 没有使用继承 那么就不用处理继承 */
  21. if (bd.getParentName() == null) {
  22. // Use copy of given root bean definition.
  23. /*如果 mbd 是 root bean*/
  24. if (bd instanceof RootBeanDefinition) {
  25. /*克隆一份保存*/
  26. mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
  27. }
  28. else {
  29. /*否则直接创建一个root bean*/
  30. mbd = new RootBeanDefinition(bd);
  31. }
  32. }/*说明当前beanName 对应的 beanDefinition 存在继承关系*/
  33. else {
  34. /*表示bd 的父信息*/
  35. BeanDefinition pbd;
  36. try {
  37. /*处理beanName 拿到处理了别名和&的真是父bd beanName 名称*/
  38. String parentBeanName = transformedBeanName(bd.getParentName());
  39. /*条件成立 说明 子 bd 和父 bd 名称不一样,就是普通情况*/
  40. if (!beanName.equals(parentBeanName)) {
  41. /*递归当前方法,最终返回父 bd 信息*/
  42. pbd = getMergedBeanDefinition(parentBeanName);
  43. }
  44. else {/*特殊:父子bd名称一样*/
  45. BeanFactory parent = getParentBeanFactory();
  46. if (parent instanceof ConfigurableBeanFactory) {
  47. pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
  48. }
  49. else {
  50. throw new NoSuchBeanDefinitionException(parentBeanName,
  51. "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
  52. "': cannot be resolved without a ConfigurableBeanFactory parent");
  53. }
  54. }
  55. }
  56. catch (NoSuchBeanDefinitionException ex) {
  57. throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
  58. "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
  59. }
  60. // 按照父bd信息创建 mbd 对象
  61. mbd = new RootBeanDefinition(pbd);
  62. // 用子bd 覆盖mbd信息,以子bd 为基准 父 bd为辅
  63. mbd.overrideFrom(bd);
  64. }
  65. // Set default singleton scope, if not configured before.
  66. if (!StringUtils.hasLength(mbd.getScope())) {
  67. mbd.setScope(SCOPE_SINGLETON);
  68. }
  69. // A bean contained in a non-singleton bean cannot be a singleton itself.
  70. // Let's correct this on the fly here, since this might be the result of
  71. // parent-child merging for the outer bean, in which case the original inner bean
  72. // definition will not have inherited the merged outer bean's singleton status.
  73. if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
  74. mbd.setScope(containingBd.getScope());
  75. }
  76. // Cache the merged bean definition for the time being
  77. // (it might still get re-merged later on in order to pick up metadata changes)
  78. if (containingBd == null && isCacheBeanMetadata()) {
  79. /*缓存合并后的 mbd信息*/
  80. this.mergedBeanDefinitions.put(beanName, mbd);
  81. }
  82. }
  83. if (previous != null) {
  84. copyRelevantMergedBeanDefinitionCaches(previous, mbd);
  85. }
  86. return mbd;
  87. }
  88. }

这里面需要关注的点有两个:

  1. 如何处理bean的名字 **transformedBeanName()**
  2. 如何合并bd信息 **getMergedBeanDefinition()**


4.处理bean的名字

  1. protected String transformedBeanName(String name) {
  2. /*
  3. * 返回 BeanFactoryUtils.transformedBeanName(name) 处理完的bean name ,这里也可能是别名。
  4. * spring的bean别名是通过aliasMap保存的。
  5. * {C:B,B:A} a有一个别名叫做 b b有一个别名叫做 c
  6. *
  7. * 通过这个方法canonicalName 去处理 bean的名字 和别名之间的关系 ,最终返回的是 bean 的真实名字。
  8. * */
  9. return canonicalName(BeanFactoryUtils.transformedBeanName(name));
  10. }

4.1 canonicalName()

处理bean的名字与别名。

  1. public String canonicalName(String name) {
  2. /*假设传入c*/
  3. String canonicalName = name;
  4. // Handle aliasing...
  5. String resolvedName;
  6. do {
  7. /*根据c会从map拿到b*/
  8. resolvedName = this.aliasMap.get(canonicalName);
  9. /*如果获取到的结果不是null*/
  10. if (resolvedName != null) {
  11. /*赋值再次循环拿*/
  12. canonicalName = resolvedName;
  13. }
  14. }
  15. /*当resolvedName是空的时候,那么此时的canonicalName一定是最终的名字,返回即可。*/
  16. while (resolvedName != null);
  17. return canonicalName;
  18. }

4.2 BeanFactoryUtils.transformedBeanName(name)

  1. public static String transformedBeanName(String name) {
  2. /*断言*/
  3. Assert.notNull(name, "'name' must not be null");
  4. /*如果当前bean对象不是 & 开头 (说明是正常bean对象实例) 直接返回*/
  5. if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
  6. return name;
  7. }
  8. /*
  9. * 这里是拿工厂bean的逻辑:
  10. * transformedBeanNameCache:缓存处理完&开头的beanName,提升性能
  11. * map.computeIfAbsent(k,v) 说明:
  12. * 当map中对应的k ==null || v ==null 这次写操作就会成功,并且返回 k v,
  13. * 否则就会失败,并且返回原有的k v。
  14. */
  15. return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
  16. /**
  17. * 假设bean name = &abc
  18. * 判断如果name不是以 &开头 跳出循环 最终会返回 abc。
  19. */
  20. do {
  21. beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
  22. }
  23. while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
  24. return beanName;
  25. });
  26. }

5.合并bd信息

**getMergedBeanDefinition()**

  1. protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
  2. // Quick check on the concurrent map first, with minimal locking.
  3. /*从缓存获取*/
  4. RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
  5. /*缓存有,直接返回*/
  6. if (mbd != null && !mbd.stale) {
  7. return mbd;
  8. }
  9. /*真正的合并 bd 的逻辑*/
  10. return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
  11. }
  1. protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
  2. throws BeanDefinitionStoreException {
  3. return getMergedBeanDefinition(beanName, bd, null);
  4. }

再往下其实又回到了上面的**getMergedBeanDefinition()**,递归去处理bd信息。

合并完bd信息之后就是判断是否是工厂bean的逻辑,想要获取工厂bean,在前面提到过,需要在bean的名字前面加一个 & 。

默认情况下,我们要看单实例bean的获取过程,此时我们去看 **getBean()**

6.获取单实例bean对象

**getBean()**

  1. @Override
  2. public Object getBean(String name) throws BeansException {
  3. /*真正加载bean的方法*/
  4. return doGetBean(name, null, null, false);
  5. }

**doGetBean()** 返回一个指定的bean实例,这个bean可以是共享的,也可以是单例的。

  1. protected <T> T doGetBean(
  2. String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
  3. throws BeansException {
  4. /*
  5. * 处理转换bean名字,可能是一个别名,也可能是一个带着& 开头的beanName
  6. * 别名:重定向出来真的beanName
  7. * &开头:说明要获取的bean实例对象实际上是一个工厂bean
  8. * FactoryBean :如果某个bean的配置特别复杂,使用spring管理不容易...不够灵活,想要使用编码的形式去构建它,
  9. * 那么你就可以提供一个构建该bean实例的工厂,这个工厂就是factoryBean接口
  10. * factoryBean接口的实现类还是需要spring来管理的。
  11. * 这里就涉及到两种对象:一种是beanFactory实现类 另一个是FactoryBean内部管理的对象。
  12. *
  13. * 如果要获取工厂bean,需要获取 &
  14. * 如果要拿factoryBean内部管理的对象,直接传name 不需要带着 &
  15. */
  16. String beanName = transformedBeanName(name);
  17. //保留返回值的
  18. Object beanInstance;
  19. /*到缓存中获取共享单实例 第一次去缓存拿*/
  20. /**
  21. * 1.第一次经过这里是创建man的时候,首先去缓存获取,但是这个时候,man对象时第一次创建,所以什么都拿不到
  22. * 2.此时man在第三级缓存,然后去拿women,这个时候women还没创建,所以锤子也拿不到
  23. * 3.第三次经过这里的时候,实际上就是women创建完了,放到三级缓存了,然后发现属性赋值的时候需要man,又通过getBean来拿,
  24. * 这个时候,在第三级缓存拿到了早期对象的引用,然后并对man进行一个缓存升级 ,从 三级缓存升级到了二级
  25. */
  26. Object sharedInstance = getSingleton(beanName);
  27. /*此时的逻辑应该是从二级缓存拿到了早期暴露的bean实例,并且属性没有填充*/
  28. /*这里如果是第一次创建bean实例,上面从一级缓存实际上是啥也没拿到,所以走到这里,实例是null。*/
  29. if (sharedInstance != null && args == null) {
  30. if (logger.isTraceEnabled()) {
  31. if (isSingletonCurrentlyInCreation(beanName)) {
  32. logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
  33. "' that is not fully initialized yet - a consequence of a circular reference");
  34. }
  35. else {
  36. logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
  37. }
  38. }
  39. /*
  40. * 这里为什么又要包装一层呢?
  41. * 从ioc中拿到的对象可能是普通的单实例,也可能是FactoryBean实例
  42. * 如果是FactoryBean实例,还要考虑进行处理 主要看name带不带 &
  43. * 带&说明这次getBean想要拿工厂bean,否则想要拿 FactoryBean 内部管理的 bean 实例
  44. */
  45. /**
  46. * 1.走到这里是什么时候?创建man,然后对man进行属性赋值,发现需要women,然后递归去创建women,然后对women进行属性赋值,
  47. * 然后发现需要man,然后从缓存拿,恰好此时从三级缓存拿到了,早期man对象的引用,这个时候,这里啥也没干,直接return
  48. */
  49. beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  50. }
  51. /*
  52. * 执行到这里的情况:sharedInstance == null || args != null
  53. * 1. 二级缓存未拿到bean实例
  54. * 2. 二级缓存拿到了bean实例,但是属性已经填充完了 !!!这是不可能的,这样的话就在一级缓存了。
  55. *
  56. * 缓存没有想要的数据
  57. * 1.原型循环依赖问题的判定
  58. */
  59. else {
  60. /*
  61. * 原型循环依赖的判定
  62. * eg: a(prototype) - b b - a (prototype)
  63. * 1.会像正在创建中的原型集合添加 a
  64. * 2.创建 a 早期对象 二级缓存
  65. * 3.处理 a的依赖 发现 a 依赖 b 类型
  66. * 4.触发 spring getBeab(b.class) 的操作
  67. * 5.根据 b 的构造方法 反射创建 b 的早期实例
  68. * 6.spring 处理 b 对象的依赖发现依赖了 a
  69. * 7.所以spring砖头回来再次获取 a getBean(a.class)
  70. * 8.程序再次来到这里会判断当前要获取的a对象是不是正在创建中 如果是循环依赖 会返回true ,最终抛出异常 结束了循环依赖注入
  71. */
  72. if (isPrototypeCurrentlyInCreation(beanName)) {
  73. throw new BeanCurrentlyInCreationException(beanName);
  74. }
  75. /*父子容器相关的处理逻辑*/
  76. BeanFactory parentBeanFactory = getParentBeanFactory();
  77. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  78. // Not found -> check parent.
  79. String nameToLookup = originalBeanName(name);
  80. if (parentBeanFactory instanceof AbstractBeanFactory) {
  81. return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
  82. nameToLookup, requiredType, args, typeCheckOnly);
  83. }
  84. else if (args != null) {
  85. // Delegation to parent with explicit args.
  86. return (T) parentBeanFactory.getBean(nameToLookup, args);
  87. }
  88. else if (requiredType != null) {
  89. // No args -> delegate to standard getBean method.
  90. return parentBeanFactory.getBean(nameToLookup, requiredType);
  91. }
  92. else {
  93. return (T) parentBeanFactory.getBean(nameToLookup);
  94. }
  95. }
  96. /*穿的是false就成立*/
  97. if (!typeCheckOnly) {
  98. /*
  99. * 将指定的 bean 标记为已创建(或即将创建)。
  100. * 允许 bean 工厂优化其缓存以重复创建指定 bean。
  101. */
  102. /**
  103. * 1.第一次创建man的时候,经过这里,标记man正在创建中
  104. * 2.第二次经过这里的时候,就是对man进行属性赋值的过程中,发现依赖women,所以去走getBean逻辑。这个时候去标记women也是正在被创建中
  105. */
  106. markBeanAsCreated(beanName);
  107. }
  108. StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
  109. .tag("beanName", name);
  110. try {
  111. if (requiredType != null) {
  112. beanCreation.tag("beanType", requiredType::toString);
  113. }
  114. /*获取合并beanDefinition信息
  115. * 为什么需要合并?
  116. * bd 支持继承 子 会 继承 父亲 的所有 信息
  117. * */
  118. RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  119. /*判断当前mbd是不是抽象的,如果是抽象的,需要抛出异常,因为抽象的bd不能创建实例,只能作为模板让子bd继承*/
  120. checkMergedBeanDefinition(mbd, beanName, args);
  121. // Guarantee initialization of beans that the current bean depends on.
  122. /*
  123. * depends-on 属性处理
  124. * <bean name="A" depends-on="B" />
  125. * <bean name="B" />
  126. *
  127. * 循环依赖问题 b - a a - b
  128. * spring是处理不了这种情况的,需要报错
  129. * spring需要发现这种情况的产生:
  130. * 如何发现?依靠两个map
  131. * 1.dependentBeanMap 记录依赖当前beanName的其他beanName
  132. * 2.dependenciesForBeanMap 记录当前bean依赖的其他bean集合
  133. * */
  134. String[] dependsOn = mbd.getDependsOn();
  135. if (dependsOn != null) {
  136. for (String dep : dependsOn) {
  137. /*判断循环依赖*/
  138. if (isDependent(beanName, dep)) {
  139. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  140. "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
  141. }
  142. /*
  143. * 注册依赖关系
  144. * 1.记录a依赖了谁
  145. * 2.记录谁依赖了b
  146. * */
  147. registerDependentBean(dep, beanName);
  148. try {
  149. getBean(dep);
  150. }
  151. catch (NoSuchBeanDefinitionException ex) {
  152. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  153. "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
  154. }
  155. }
  156. }
  157. // 创建单实例
  158. if (mbd.isSingleton()) {
  159. /*第二个 getSingthon() 创建实例并返回*/
  160. /**
  161. * 1.第一次经过这里是去创建man对象
  162. * 2.创建women对象
  163. */
  164. sharedInstance = getSingleton(beanName, () -> {
  165. try {
  166. return createBean(beanName, mbd, args);
  167. }
  168. catch (BeansException ex) {
  169. // Explicitly remove instance from singleton cache: It might have been put there
  170. // eagerly by the creation process, to allow for circular reference resolution.
  171. // Also remove any beans that received a temporary reference to the bean.
  172. destroySingleton(beanName);
  173. throw ex;
  174. }
  175. });
  176. /*
  177. * 这里为什么不直接返回 ,还调用 这个方法?
  178. * 创建出来的单实例bean也可能是工厂bean对象,所以需要根据名字判断到底返回
  179. * bean对象还是工厂bean
  180. * */
  181. beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  182. }
  183. /*多例bean的创建*/
  184. else if (mbd.isPrototype()) {
  185. // It's a prototype -> create a new instance.
  186. Object prototypeInstance = null;
  187. try {
  188. /*记录当前线程相关的正在创建的原型对象beanName*/
  189. beforePrototypeCreation(beanName);
  190. /*创建对象*/
  191. prototypeInstance = createBean(beanName, mbd, args);
  192. }
  193. finally {
  194. /*从正在创建中的集合中移除*/
  195. afterPrototypeCreation(beanName);
  196. }
  197. beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  198. }
  199. /*other作用域: 略 ....*/
  200. else {
  201. String scopeName = mbd.getScope();
  202. if (!StringUtils.hasLength(scopeName)) {
  203. throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
  204. }
  205. Scope scope = this.scopes.get(scopeName);
  206. if (scope == null) {
  207. throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
  208. }
  209. try {
  210. Object scopedInstance = scope.get(beanName, () -> {
  211. beforePrototypeCreation(beanName);
  212. try {
  213. return createBean(beanName, mbd, args);
  214. }
  215. finally {
  216. afterPrototypeCreation(beanName);
  217. }
  218. });
  219. beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  220. }
  221. catch (IllegalStateException ex) {
  222. throw new ScopeNotActiveException(beanName, scopeName, ex);
  223. }
  224. }
  225. }
  226. catch (BeansException ex) {
  227. beanCreation.tag("exception", ex.getClass().toString());
  228. beanCreation.tag("message", String.valueOf(ex.getMessage()));
  229. cleanupAfterBeanCreationFailure(beanName);
  230. throw ex;
  231. }
  232. finally {
  233. beanCreation.end();
  234. }
  235. }
  236. /**
  237. * 1.走到这里的逻辑:对man进行属性赋值,递归创建women,对women进行属性赋值,然后从缓存拿到了man
  238. */
  239. return adaptBeanInstance(name, beanInstance, requiredType);
  240. }

这个方法的逻辑有点多,进行一个简单的梳理:

  1. 首先上来先处理bean的名字 **transformedBeanName(name)**
  2. 然后尝试通过 **getSingleton(beanName) **去一级缓存拿数据,但是这个时候这个bean对象还没有创建过,此时是拿不到数据的。
  • 如果说拿到了bean对象,那么就再通过 **getObjectForBeanInstance() **对bean对象进行一层包装。

    这里为什么又要包装一层呢? 从IOC中拿到的对象可能是普通单实例bean对象,也可能是一个工厂bean对象。 如果是工厂bean对象,还需要考虑是不是需要处理,主要是看名字里面带不带 & 。 如果带 & ,就是想要拿工厂本身,如果不带 & ,其实就是想拿工厂bean生产的对象。

  1. 正常第一次去获取bean对象的时候,是在缓存拿不到数据的,所以会走else的逻辑。
  2. 判断是不是原型模式的循环依赖,如果是的话,抛出异常。
  3. 然后就是护理父子容器相关的逻辑
  4. 如果是第一次创建bean,就会通过一个状态位来标记bean正在创建中
  5. 获取合并后的bd信息
  6. 判断当前bean对象是不是抽象的,如果是抽象的,需要跑出异常,因为抽象的bean是模板bean,不能创建实例
  7. 判断是不是发生互相依赖,注意是互相依赖,不是循环依赖,如果是发生了互相依赖,则抛出异常。

    互相依赖:bean标签或者@Bean 注解里面配置了 **depends-on="B" a->b , b->a**

    循环依赖:a里面有个属性叫做b,b里面有个属性a �

  8. 注册依赖关系,记录当前bean依赖了谁,谁依赖了当前bean

  9. 判断如果是单实例bean,这次就会通过**getSingleton()->createBean()**去创建bean对象
  10. 然后再通过**getObjectForBeanInstance() **对bean对象进行一层包装
  11. 如果是原型实例的bean对象,就会走多实例bean创建的流程,其实还是通过**createBean()**去创建对象,只是不会被一级缓存所缓存。
  12. 对于其他作用域的bean对象,则走他们的创建逻辑,再次不作为重点内容分析。
  13. 最终的逻辑**adaptBeanInstance()**其实就是对循环依赖的处理,对 A对象属性赋值的时候,发现需要B对象。然后从一级缓存拿发现没有,就走这里递归去创建B对象,从缓存拿到A对象,对B对象进行属性赋值。

7.getSingleton()

看一下这个方法,从缓存来获取bean。这个方法在 **DefaultSingletonRegistry** 中。

    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        /*方法重载   allowEarlyReference  是否允许拿到早期引用*/
        return getSingleton(beanName, true);
    }

�这里发生了方法重载。这个方法挺叼的,根据名称来返回单实例bean对象,能够解决循环依赖。

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        /*通过名字去一级缓存拿单实例bean对象*/
        Object singletonObject = this.singletonObjects.get(beanName);
        /*如果拿到的对象实例是null,有几种情况?
        * 1.单实例确实没创建呢
        * 2. 当前正在创建中,发生了循环依赖了,这个时候实例其实在二级缓存
        *
        * 循环依赖:
        * A->B  B->A
        * 单实例的循环依赖有几种?
        * 1.构造方法   无解
        * 2.setter    有解   通过三级缓存
        *
        * 三级缓存实际上如何解决的循环依赖?
        * 利用bean的中间状态 :已经实例化但是还未初始化
        * A-B  B->A  setter依赖
        * 1. 假设spring先实例化A,首先拿到A的构造方法,反射创建A的早期实例对象,这个早期对象被包装了一下,
        * 变成ObjectFactory对象,放到三级缓存。
        * 2. 处理A的依赖数据,检查发现 A依赖B ,所以,spring 根据 B的类型去容器中去getBean(B.class) ,这里就是递归了
        * 3. 首先拿到B的构造方法,反射创建B的早期实例对象,把B包装成ObjectFactory对象,放到三级缓存。
        * 4. 处理Bde 依赖数据,检查发现,B依赖对象A,所以接下来,spring就会根据A类型去容器去getBean(A.class) 对象,这个时候又递归了
        * 5. 程序还会走到当前方法getSingleton
        * 6. 条件一成立,条件二成立。
        *
        */
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            /*从二级缓存拿数据*/
            singletonObject = this.earlySingletonObjects.get(beanName);
            /*条件成立说明二级缓存没有  去三级缓存拿*/
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    /*
                    * spring为什么需要有三级缓存,而不是只有二级缓存?
                    * AOP 靠什么实现呢?动态代理  jdk cglib
                    * 代理:静态代理:需要手动写代码实现新的JAVA文件,这个JAV类需要和代理对象实现同一个接口,内部维护一个被代理对象
                    *     代理类在接口调用原生对象前后可以加一些逻辑。
                    *     代理对象和被代理对象是两个不同的内存地址,一定是不一样的
                    *        动态代理:... 不需要人为写代码了,而是依靠字节码框架动态生成字节码文件,然后jvm在进行加载,然后也是一样
                    *     也是去new代理对象,这个代理对象没啥特殊的,也是内部保留了原生对象,然后再调用原生对象前后实现的字节码增强。
                    * 两者共同点:代理对象和被代理对象实际上都不是同一内存地址
                    *
                    * 三级缓存在这里有什么意义呢?
                    * 三级缓存里面保存的是对象工厂,这个对象工厂内部保留着原生对象的引用,ObjectFactory的实现类,getObject方法,
                    * 需要考虑一个问题:到底是返回原生的,还是增强的?
                    * getObject会判断当前早期实例是否需要被增强,如果是 那么提前完成动态代理增强,返回代理对象,否则,返回原生对象。
                    *
                    */
                    /*从一级缓存拿*/
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        /*从二级缓存拿*/
                        singletonObject = this.earlySingletonObjects.get(beanName);

                        if (singletonObject == null) {
                            /*从三级缓存拿*/
                            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                            /*条件成立:说明第三级缓存有数据。这里就涉及到了缓存的升级 ,很简单 ,从三级挪到二级 ,再反手干掉三级的。*/
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }
                }
            }
        }
        return singletonObject;
    }

梳理一下这个方法的大体逻辑:(我们现在走的是单实例bean创建的流程,所以假设我们正在创建一个单实例bean,执行到了这里,三级缓存与循环依赖的问题会在后续文章分析。)

  1. 先根据名字去一级缓存拿bean,此时是拿不到的。
  2. 判断当前bean,是不是单实例bean对象,是不是正在创建中?

    走这里的逻辑就是发生了循环依赖:

    1. 假设spring先实例化A,首先拿到A的构造方法,反射创建A的早期实例对象,这个早期对象被包装了一下,变成ObjectFactory对象,放到三级缓存。 � �2. 处理A的依赖数据,检查发现 A依赖B ,所以,spring 根据 B的类型去容器中去getBean(B.class) ,这里就是递归了 �
    2. 首先拿到B的构造方法,反射创建B的早期实例对象,把B包装成ObjectFactory对象,放到三级缓存。 �
    3. 处理Bde 依赖数据,检查发现,B依赖对象A,所以接下来,spring就会根据A类型去容器去getBean(A.class) 对象,这个时候又递归了 �
    4. 程序还会走到当前方法getSingleton �
  • 首先去二级缓存拿数据,这个时候二级缓存是拿不到数据的,所以会继续往下走
  • 再次尝试从一级缓存和二级缓存拿,这个时候其实还是拿不到的,所以从三级缓存来拿
  • 如果三级缓存拿到了数据,那就进行缓存的升级

    把三级缓存的对象拿到二级缓存,三级缓存的对象干掉。

8.思考与沉淀

spring为什么需要有三级缓存,而不是只有二级缓存?
AOP 靠什么实现呢?动态代理 jdk cglib
代理:静态代理:需要手动写代码实现新的JAVA文件,这个JAV类需要和代理对象实现同一个接口,内部维护一个被代理对象
代理类在接口调用原生对象前后可以加一些逻辑。
代理对象和被代理对象是两个不同的内存地址,一定是不一样的
动态代理:… 不需要人为写代码了,而是依靠字节码框架动态生成字节码文件,然后jvm在进行加载,然后也是一样
也是去new代理对象,这个代理对象没啥特殊的,也是内部保留了原生对象,然后再调用原生对象前后实现的字节码增强。
两者共同点:代理对象和被代理对象实际上都不是同一内存地址

三级缓存在这里有什么意义呢?
三级缓存里面保存的是对象工厂,这个对象工厂内部保留着原生对象的引用,ObjectFactory的实现类,getObject方法,
需要考虑一个问题:到底是返回原生的,还是增强的?
getObject会判断当前早期实例是否需要被增强,如果是 那么提前完成动态代理增强,返回代理对象,否则,返回原生对象。

9.getObjectForBeanInstance()

这个方法是获取给定的bean实例对象,如果是工厂bean,则根据名字返回工厂本身或者其创建的对象。

    /**
     * 获取给定 bean 实例的对象,如果是 FactoryBean,则是 bean 实例本身或其创建的对象。
     * @param beanInstance   共享单实例对象
     * @param name  未处理 & 的 name
     * @param beanName  处理过& 和别名后的name
     * @param mbd the merged bean definition  合并过后的beanDefinition信息
     * @return the object to expose for the bean
     */
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
        /*判断当前的name是不是&开始的,条件成立,说明当前要获取的是工厂bean对象*/
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            /*条件成立:说明但实例对象不是工厂bean接口的实现类  直接报错*/
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            /*打标  给当前bean对应的mbd打标,记录他表达的实例是一个工厂bean*/
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            return beanInstance;
        }

        /*
        * 执行到这里有几种情况?
        * 1.当前bean实例是普通单实例
        * 2.当前bean实例是工厂bean接口实现类,但是当前要获取的是工厂内部管理的bean实例
        */
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }
        /*保存工厂bean实例的getobject值得*/
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            /*尝试到缓存获取工厂bean*/
            object = getCachedObjectForFactoryBean(beanName);
        }
        /*此时说明缓存没有,需要到工厂bean getObject 获取*/
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // 条件一几乎恒成立   条件二:判断spring中当前是否有当前beanName的bd信息
            if (mbd == null && containsBeanDefinition(beanName)) {
                /*拿到合并后的bd信息
                * 为什么是合并后的呢?
                * 因为bd支持继承的,合并后的bd信息是包含继承回来的bd
                * */
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            /*synthetic默认值是false ,表示这是一个用户对象  如果是 true 表示是系统对象*/
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            /*到这里说明  说明真正的去执行 getBean() 的逻辑   time 【51:32】*/
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
  1. 判断当前的name是不是 & 开始的,条件成立,说明当前要获取的是工厂bean对象
  • 如果当前bean独享没有实现工厂bean接口,直接报错
  • 打标:给当前bean对应的mbd打标,记录他表达的实例是一个工厂bean对象
  • 返回bean实例
  1. 判断如果当前bean没有实现工厂bean接口,(思考一下,走到这里的逻辑,其实要么是单实例bean,要么是获取工厂bean创建的对象),既然没有实现工厂bean接口,所以这里的逻辑就是处理单实例bean的。
  • 直接返回就行了
  1. 走到这里的逻辑就是一种情况:获取工厂bean创建的bean对象。
  • 在mbd打标,表示是一个工厂bean对象
  • 如果缓存里面没有当前bean工厂生产的对象,需要通过工厂bean的**getBean()**去获取。
  • 判断有没有bd信息,如果没有就合并bd信息得到mbd信息
  • 然后再通过**getObjectFromFactoryBean() **根据mbd信息去获取bean对象

9.1 getObjectFromFactoryBean()

这个方法的逻辑上存在问题,但是不影响分析。

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        /*如果是已经存在的单实例bean对象*/
        if (factory.isSingleton() && containsSingleton(beanName)) {
            /*加锁 内部逻辑是串行化的,不存在并发*/
            synchronized (getSingletonMutex()) {
                /*先从缓存获取*/
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    /*这里已经是空了*/
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    // Only post-process and store if not put there already during getObject() call above
                    // (e.g. because of circular reference processing triggered by custom getBean calls)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    /*这里一定是空,因为是串行化的方法,所以逻辑有问题*/
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    } else {
                        if (shouldPostProcess) {
                            /*判断当前实例是否被创建    逻辑有问题    明明上面就是没创建 */
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            beforeSingletonCreation(beanName);
                            try {
                                /*执行后置处理器的逻辑*/
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            } catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            } finally {
                                afterSingletonCreation(beanName);
                            }
                        }
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
            /*工厂bean对象内部维护的对象不是单实例,每次都是一个新对象*/
        } else {
            /*直接拿*/
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (shouldPostProcess) {
                try {
                    /*后置处理器的逻辑*/
                    object = postProcessObjectFromFactoryBean(object, beanName);
                } catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

if里面的判断是不会成立的,所以直接看else的逻辑。

通过委派模式委派给**doGetObjectFromFactoryBean()**去拿bean对象,然后再执行后置处理器的逻辑。

继续往下分析:

9.2 doGetObjectFromFactoryBean()

    private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
        Object object;
        try {
            object = factory.getObject();
        }
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }

        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();
        }
        return object;
    }

这里面的核心代码其实就是只有一句:调用工厂bean的**factory.getObject()** 获取bean对象。

剩余的**createBean()** & **adaptBeanInstance()****createBean()**创建bean的逻辑会在下一篇中深入分析,**adaptBeanInstance()**循环依赖相关的逻辑会在后续的三级缓存与循环依赖篇中分析,与本次的创建单实例bean对象关系并不大。至此,整个**getBean()**就分析完了。

10.触发所有单实例bean初始化后的回调逻辑

**preInstantiateSingletons()**里面通过 getBean() 方法实例化完所有的单实例bean以后,就会触发所有 **SmartInitializingSingleton****afterSingletonsInstantiated()**

�这个组件具体的作用,在前面的Spring组件与注解篇里面已经详细介绍过,在此不再赘述。

        // 触发所有的单实例bean的初始化后的回调逻辑
        for (String beanName : beanNames) {
            //从一级缓存获取单实例bean
            Object singletonInstance = getSingleton(beanName);
            //类型断言,执行回调
            /*SmartInitializingSingleton里面有一个方法 afterSingletonsInstantiated 这个方法需要在创建好单实例bean之后调用一下*/
            if (singletonInstance instanceof SmartInitializingSingleton) {
                StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
                        .tag("beanName", beanName);
                SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                //这里就是触发初始化后的回调逻辑
                smartSingleton.afterSingletonsInstantiated();
                smartInitialize.end();
            }
        }

下一篇,我们将继续分析bean对象的创建逻辑 **createBean()**