Spring IOC 容器源码简单分析(三)——创建单例Bean

前言

Spring IOC 容器源码简单分析(二)——获取单例Bean

我们说了获取bean相关的一系列方法,就是先去缓存中获取,如果缓存没命中的话, 肯定就需要去创建bean了,那么在哪创建单例呢, 这就是上篇遗留的<5>和<6>的问题了,这个创建的过程很长,这篇文章可能一下写不完,慢慢来吧。

话不多说,let’s go。

由于接上文,因此还是沿用上次的习惯。

<6> 解析createBean

由于<5>的时候引用到了<6>,所以先来分析<6>的情况。

// 前情提要:
// beanName是根据name转换好的。 mbd 是 合并后的BeanDefinition, 
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // 解析bean的class。
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }
  
    try {
        // Spring统一将 lookup-method 和 replace-method 称为override method,处理的就是这俩。
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                                               beanName, "Validation of method overrides failed", ex);
    }

    try {
        // <6-1> 在 bean 初始化前应用后置处理,如果后置处理返回的 bean 不为空,则直接返回
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                                        "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // <6-2> 创建bean。
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

简单描述一下:

  1. 解析 bean class
  2. 处理 lookup-method 和 replace-method 配置
  3. 在 bean 初始化前应用后置处理,若后置处理返回的 bean 不为空,则直接返回
  4. 否则,调用 doCreateBean 创建 bean 实例。

总之,就是能返回bean实例。

<6-1>解析resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   // 检测是否解析过,该值会在下面的代码中会被设置
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // 确保BeanDefinition 不是合成的(不确定这句话是不是对的,因为翻阅了很久还是没找到它设为true的时机)
      // 同时 此工厂是否拥有InstantiationAwareBeanPostProcessor,它将在创建时应用于单例bean。
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
             // 前置
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               // 后置处理。
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}


protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // bean 初始化前置处理
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

<6-2> 解析doCreateBean

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

		// BeanWrapper 是一个接口,它包裹着 bean 实例。
		BeanWrapper instanceWrapper = null;
		// 如果是单例。
		if (mbd.isSingleton()) {
			// 老实说这个缓存我不知道是干啥的。
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// <6-2-1> 在这create Bean。
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// 获取实例化好的bean,暂时没填充属性。
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
		// 允许后置处理器修改合并的bean定义。
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// 如果是单例的 && 允许循环依赖的 && 存于创建状态中。
		// 看单词意思,早期单例曝光,这个变量用于解决循环依赖。
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
            // 添加工厂对象到 singletonFactories 缓存中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// 初始化bean实例。
		Object exposedObject = bean;
		try {
			// <6-2-2> 在这,填充前面	实例化好的bean的属性。
			populateBean(beanName, mbd, instanceWrapper);
        	 // <6-2-3> 处理 bean 初始化完成后的各种回调。
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		if (earlySingletonExposure) {
            // 还是获取早期引用。
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
                // 如果bean没有被wrapper封装。
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
                // 说明被wrapper封装了, allowRawInjectionDespiteWrapping 变量为true时表示,尽管被封装了,但还是允许原始的bean注入。
                // 那么下面的条件是, 被封装了 && 不允许原始的bean被注入 && 该bean有依赖的bean
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
                    // 表示实际依赖的对象。
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
                        // 如果已经创建的bean中包含该dependentBean,那么会返回false
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
                    // 那么就会报出异常,大概就是,作为循环引用,已经被注入到其他bean中了,但没使用到使用bean的最终版本。
					if (!actualDependentBeans.isEmpty()) {
						// 抛异常的,我给注释了。
					}
				}
			}
		}

		
		try {
            // 注册销毁逻辑
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

这里又延伸了其他的方法,还是鉴于篇幅的原因,我就不在此进行叙述,下篇见。

然后也简单概括一下该方法的整体逻辑。

  1. 还是先从缓存中获取BeanWrapper ,并清除掉。
  2. 缓存没有就去创建,并包裹在BeanWrapper,但此时还没有填充属性 。
  3. 如果允许暴露早期引用,就放进调用addSingletonFactory方法,用于解决循环依赖。
  4. 调用 populateBean 方法填充属性,调用 initializeBean 方法完成剩下的初始化工作。
  5. 注册销毁逻辑。

感觉spring写的真的很复杂,到第三篇才开始创建bean了,还只是刚开始创建,属性填充啥的都得下篇。

<5>解析getSingleton

这个要和之前<2>的getSingleton区分一下哈,不是一个方法哈。

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 + "'");
         }
         // 到这里说明为空,那么需要将beanName放入到singletonsCurrentlyInCreation 和 inCreationCheckExclusions 中。
         // 表示该beanName正在创建。
         beforeSingletonCreation(beanName);
         boolean newSingleton = false;
         boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
         if (recordSuppressedExceptions) {
            this.suppressedExceptions = new LinkedHashSet<>();
         }
         try {
             // 就是这里调用到了<6>!
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         catch (IllegalStateException ex) {
            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 和 inCreationCheckExclusions 中移除。
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            // 添加到singletonObjects和 registeredSingletons 中,并移除
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

简单概括一下:

  1. 先获取缓存中的bean,有就直接返回了。
  2. 否则,将beanName放入到singletonsCurrentlyInCreation 和 inCreationCheckExclusions 中。
  3. 调用singletonFactory.getObject 方法从而调用 createBean 方法创建 bean 实例
  4. 将 beanName 从 singletonsCurrentlyInCreation 集合中移除,同时添加缓存。

总结

这里由于是倒着写 5、6的,可能有些许的不好理解 ,主要是5中的调用singletonFactory.getObject可以调用到<6> createBean,至于<6>中的细节,在本篇中已写,耐心点看,其中还有创建单例的具体,我将在下篇中写到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值