【Spring 源码解析】Spring XML方式准备创建bean

1、前言

上文Spring XML方式获取bean源码初步解析讲述了spring 创建bean的概览后对源码初步的解析。

主要涉及的是:

2.1、获取真正的beanName
2.2、从缓存中获取bean
2.3、获取bean实例
2.4、检测是否是抽象
2.5、处理依赖的bean
2.6、判断是否是单例
2.7、判断是否是原型
2.8、非单例和原型的作用域统一处理
2.9、对获取bean的类型和需要的类型进行校验

其中对于除创建bean之外的步骤都进行了解析,此篇就继续说下创建bean之前的任务。

其中spring对创建bean的步骤进行了分类,分别为单例的情况,原型模式的情况和其他情况三种。创建bean的方法都是相同的。处理原型模式和其他都对创建前后对创建bean做了缓存处理。

这里着重说下单例的情况,其实细节稍微不同外,三种的主要步骤是相同的。

2、查看常见bean之前的细节

这里查看getSingleton创建的细节,查看方法 singletonObjects 单例获取。

sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});

这里其实有两个主要的步骤,getSingleton 和 createBean。

2.1、getSingleton 方法解析

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
      // 1.从缓存中获取
      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 + "'");
        }
        // 2.放入正在创建的缓存对象
        beforeSingletonCreation(beanName);
        boolean newSingleton = false;
        boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
        if (recordSuppressedExceptions) {
          this.suppressedExceptions = new LinkedHashSet<>();
        }
        try {
          // 3. 从单例工厂Factory中获取,初始化bean
          singletonObject = singletonFactory.getObject();
          newSingleton = true;
        }
        catch (IllegalStateException ex) {
          // Has the singleton object implicitly appeared in the meantime ->
          // if yes, proceed with it since the exception indicates that state.
          
          // 4. 从缓存中再次获取
          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;
          }
          // 从正在创建的缓存中移除
          afterSingletonCreation(beanName);
        }
        if (newSingleton) {
          // 放入缓存
          addSingleton(beanName, singletonObject);
        }
      }
      return singletonObject;
    }
  }
  1. 首先从singletonObjects缓存中获取
  2. 如果没有拿到,那么判断是否需要检测和是否正在创建中,如果是直接报错。
  3. 从传参ObjectFactory的个体Object方法实例化bean
  4. 从正在创建的缓存中移除
  5. 放入缓存,并删除过程中的加载记录
  6. 返回创建结果

2.2、createBean方法

进入createBean方法,这里是 AbstractBeanFactory 抽象方法createBean 在 AbstractAutowireCapableBeanFactory 中的实现:

@Override
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;

	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.

	// 通过beanName class 获取bean对应的Class对象
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	// 检查重写的方法
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		// 处理BeanPostProcessors 来代理实例
		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);
	}

	// 创建bean
	try {
		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. resolveBeanClass 通过beanName,class 获取bean对应的Class对象。并创建新RootBeanDefinition对象。
  2. mbdToUse.prepareMethodOverrides() 检查重写的方法,这里指的是标签解析的lookup-method 和 replaced-method 对应的方法。
  3. resolveBeforeInstantiation 实例化的前置处理工作,这里其实就是spring aop 功能实现的原理,通过代理在初始化前后做工作,返回的是可能已经是代理类对应的bean。
  4. 真正执行实例化 doCreateBean

3、总结

这里总结下这篇文章的内容,在创建bean之前的一些处理。
主要包括封装新的RootBeanDefinition对象,并把解析的class放入,然后处理重写的方法,之后处理BeanPostProcessor 处理的后置工作,最后进行真正创建bean。

下篇说下循环依赖的问题,之前的几篇也说了好几次了,下篇就总结说明下。

希望每天都有所收获,加油!共勉!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值