spring源码:bean加载之创建bean-概述

一、介绍

  我理解的bean加载,是程序从IOC容器获取bean的过程,而创建bean实例只是其中的一个步骤。因为bean实例被创建后,会存入到DefaultSingletonBeanRegistry#singletonObjects缓存中(类型为(ConcurrentHashMap)),程序下次再获取该bean时,就不用再次创建bean实例了。
  创建bean实例的方法为:AbstractAutowireCapableBeanFactory#doCreateBean(),本章就来讲述一下这个doCreateBean()方法。

二、bean加载流程
  1. 获取用户传入name对应的beanName
  2. 尝试从缓存中获取bean实例
  3. 缓存中不存在,加载bean实例
    3.1. 检查循环依赖
    3.2 处理parentBeanFactory
    3.3 处理依赖的bean(dependsOn)
    3.4 三种bean实例的创建
     3.4.1 单例bean的创建
      3.4.1.1 获取单例bean,getSingleton()方法
      3.4.1.2 准备创建bean,createBean()方法
      3.4.1.3 创建bean,doCreateBean()方法(本章解析
     3.4.2 原型bean的创建
     3.4.3 根据scope策略创建bean
  4. 从bean实例中获取真正的对象
  5. 转换对象类型
  6. 返回对象实例
三、doCreateBean()方法流程图

在这里插入图片描述

  • 第2步,创建BeanWrapper过程中,会创建对应的bean实例
  • 第4步,提前曝光bean目的是为了解决循环依赖。具体是,把创建该bean的ObjectFactory对象存入到DefaultSingletonBeanRegistry#singletonFactories缓存中(HashMap类型),这样在出现循环依赖时,可以从这个缓存中直接取出对应的bean实例。从这里获取的bean会应用SmartInstantiationAwareBeanPostProcessor
四、源码分析
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			// 1. 清理单例缓存
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 2. 创建BeanWrapper(重要方法)
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final 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 {
					// 3. MergedBeanDefinitionPostProcessors的应用
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// 是否需要提早曝光:单例&&允许玄幻依赖&&当前bean正在创建中(重要方法)
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 4. 提前曝光bean(解决循环依赖),即在bean初始化完成前将创建实例的ObjectFactory加入工厂
			// getEarlyBeanReference()方法应用SmartInstantiationAwareBeanPostProcessor
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 5. 属性填充(重要方法)
			populateBean(beanName, mbd, instanceWrapper);
			// 6. 调用初始化方法,如init-method(重要方法)
			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);
			}
		}
		// 7. 循环依赖检查
		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			// earlySingletonReference只有在检测到有循环依赖的情况才会不为空
			if (earlySingletonReference != null) {
				// 如果exposedObject没有在初始化方法中被改变
				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);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			// 8. 注册DisposableBean(重要方法)
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}
		// 创建完成
		return exposedObject;
	}

结合doCreateBean()方法的代码来看,图中的8个步骤还算清晰。图中4个粉色步骤:创建BeanWrapper、属性填充、调用初始化方法、注册DisposableBean在后面的文章中会一一叙述。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值