Spring Ioc 之 Bean的加载(四):createBean()

上一篇文章Spring Ioc 之 Bean的加载(三):各个 scope 的 Bean 建立 咱们分析了各个做用域Bean的建立大致流程。这篇文章咱们来分析如下建立Bean的关键方法 createBean()java

createBean()

代码:spring

//AbstractAutowireCapableBeanFactory.java

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

	if (logger.isDebugEnabled()) {
		logger.debug("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.
	//判断须要建立的Bean是否能够实例化,便是否能够经过当前的类加载器加载
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	//校验和准备Bean中的方法覆盖
	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.
		//若是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 {
		//建立Bean的入口
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException ex) {
		// A previously detected exception with proper bean creation context already...
		throw ex;
	}
	catch (ImplicitlyAppearedSingletonException ex) {
		// An IllegalStateException 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是否能够实例化,便是否能够经过当前的类加载器加载app

  2. 校验和准备Bean中的方法注入ide

  3. 若是Bean配置了初始化前和初始化后的处理器,则试图返回一个须要建立Bean的代理对象函数

  4. 建立Beanpost

第1步

主要是获取bean的class,并设置到BeanDefinition中this

第2步

主要是处理方法注入
代码:.net

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exists.
	//检测是否存在方法注入,并循环预处理方法注入
	if (hasMethodOverrides()) {
		Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
		synchronized (overrides) {
		        //遍历处理
			for (MethodOverride mo : overrides) {
				prepareMethodOverride(mo);
			}
		}
	}
	}

prepareMethodOverride(mo):debug

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        // 统计注入的方法个数   
	int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
	if (count == 0) {
		throw new BeanDefinitionValidationException(
				"Invalid method override: no method with name '" + mo.getMethodName() +
				"' on class [" + getBeanClassName() + "]");
	}
        // 若是为1,则将注入方法标记为未重载
	// 注意:当有多个重载方法时,为了肯定调用哪一个具体的方法,Spring对重载方法的参数解析是很复杂的
	// 因此,若是注入方法没有被重载这里就将其标记,省去了对方法参数的解析过程,直接调用便可
	else if (count == 1) {
		// Mark override as not overloaded, to avoid the overhead of arg type checking.
		mo.setOverloaded(false);
	}
	}

代码读到这里,你们可能有疑问,从代码上看明明是处理的方法重载,可是为何处理的是方法注入呢?并且若是咱们在bean里设置几个方法重载的话,hasMethodOverrides()方法返回的是false。若是咱们打开 AbstractBeanDefinition 类的 hasMethodOverrides() 方法,就能打消咱们以前的疑问。

public boolean hasMethodOverrides() {
		return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
	}

其中methodOverrides是作什么的呢?经过类名AbstractBeanDefinition咱们能够发现,该类是BeanDefinition的一个子类,那么它保存的应该是咱们解析到的beanDefinition,spring在解析配置文件的时候,若是发现配置了replace-method或者lookup-method那么,就会对应的标签解析,并存入到 AbstractBeanDefinition 的 methodOverrides 属性中,那么当bean实例化的时候,若是检测到了methodOverrides属性不为空,则动态的为当前bean生成代理并使用相应的拦截器对bean作处理,这里你们只要把概念搞清楚便可。

第3步

主要是对bean前置后置处理器的处理,给 BeanPostProcessors 后置处理器一个返回代理对象的机会
详细代码:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		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;
	}

若是代理对象不为空,则直接返回代理对象,这一步骤有很是重要的做用,Spring 后续实现 AOP 就是基于这个地方判断的。
这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()applyBeanPostProcessorsAfterInitialization() 两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。

第4步

doCreateBean()
建立Bean

//真正建立Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {

	// Instantiate the bean.
	//BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
	        //单例模式,删除factoryBean缓存
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	        //使用合适的实例化策略来建立Bean:工厂方法、构造函数自动注入、简单初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	//从包装类中获取实例化的Bean
	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 {
			        //调用PostProcessor后置处理器,修改 BeanDefinition
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// 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) {
		if (logger.isDebugEnabled()) {
			logger.debug("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	//Bean对象的初始化,依赖注入在此触发
	//这个exposedObject在初始化完成以后返回做为依赖注入完成后的Bean
	Object exposedObject = bean;
	try {
		//将Bean实例对象封装,而且Bean定义中配置的属性值赋值给实例对象
		populateBean(beanName, mbd, instanceWrapper);
		//初始化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) {
		//获取指定名称的已注册的单例模式Bean对象
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			//根据名称获取的已注册的Bean和正在实例化的Bean是同一个
			if (exposedObject == bean) {
				//当前实例化的Bean初始化完成
				exposedObject = earlySingletonReference;
			}
			//当前Bean依赖其余Bean,而且当发生循环引用时不容许新建立实例对象
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				//获取当前Bean所依赖的其余Bean
				for (String dependentBean : dependentBeans) {
					//对依赖Bean进行类型检查
					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.
	//注册完成依赖注入的Bean
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
	}

代码很长,不过别慌,咱们来按步骤分析一波

  1. 若是是单例模式,从factoryBeanInstanceCache 缓存中获取BeanWrapper 实例对象并删除缓存
  2. 调用 createBeanInstance() 实例化 bean
    (主要是将 BeanDefinition 转换为 BeanWrapper)
  3. 后置处理
  4. 单例模式的循环依赖处理
  5. 初始化 bean 实例对象
    (属性填充)
  6. 依赖检查
  7. 注册 DisposableBean

doCreateBean() 完成 bean 的建立和初始化工做,内容太多,比较复杂,这里只列出大体流程,接下来咱们将分几篇文章来分别阐述相关内容。

相关文章
相关标签/搜索