Spring容器 —— 深入 bean 的加载(二、bean 创建基本思路分析)

bean 创建基本思路分析

本文解析了 Spring 的通常创建方法,即 doCreateBean()。首先解析源码。

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

		// 根据指定 bean 使用对应策略创建新的实例,如工厂方法、构造函数自动注入、简单初始化
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				...
				mbd.postProcessed = true;
			}
		}

		// 是否需要提前曝光:单例 & 允许循环依赖 & 当前 bean 正在创建中
		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			...
			// 提前暴露 ObjectBean
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 对 bean 进行填充,将各个属性注入
			// 若存在依赖于其他 bean 的属性,则会递归初始化依赖 bean
			populateBean(beanName, mbd, instanceWrapper);
			// 调用初始化方法,比如 init-method
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		...

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			// 有循环依赖才不为空
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						// 检查依赖
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					// 不为空表示当前 bean 创建后依赖的 bean 却没有全部创建完,即存在循环依赖
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(...);
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			// 根据 scope 注册 bean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		...

		return exposedObject;
	}

整理这个函数的思路如下:

  1. 如果是单例则需要首先清除缓存。
  2. 实例化 bean,将 BeanDefinition 转换为 BeanWrapper。
    转换的大致功能包括:
    • 如果存在工厂方法则使用工厂方法进行初始化;
    • 一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化;
    • 如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行 bean 的实例化;
  3. MergedBeanDefinitionPostProcessor 的应用
    bean 合并后的处理,Autowired 注解正是通过此方法实现诸如类型的预解析
  4. 依赖处理
    在 Spring 中会有循环依赖的存在,通过三级缓存和 ObjectFactory 提前暴露的方式解决该问题。
  5. 属性填充。将所有属性填充到 bean 实例中。
  6. 循环依赖检查。
    Spring 的循环依赖解决只对单例有效,对于 prototype 的 bean 只能抛出异常,所以这里会检测已经加载的 bean 是否已经出现了依赖循环,并判断是否需要抛出异常。
  7. 注册 DisposableBean
    如果配置了destory-method,这里需要注册以便于在销毁时候调用。
  8. 完成创建并返回

接下来我们将分步详细解析 创建 bean 的每一个步骤。

下面是相关文章索引。
创建 bean 实例 —— createBeanInstance.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值