《Spring源码深度解析》- 5BeanFactory的加载

栏目: Java · 发布时间: 5年前

内容简介:在该接口中还定义了3个方法:当配置文件中的class属性配置的实现类是FactoryBean时, 通过getBean()方法返回的不是FactoryBean本身, 而是FactoryBean#getObject()方法所返回的对象, 相当于FactoryBean#getObject()代理了getBean()方法.这个方法因为涉及循环依赖的检测, 以及涉及很多变量的记录存取, 所以让很多读者摸不着头脑. 这个方法首先尝试从singletonObjects里面获取实例, 如果获取不到, 在尝试从singlet

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		/* 
		(一). 转换对应beanName
		传入的参数name不一定就是beanName, 可能是别名, 也可能是FactoryBean, 所以需要一系列的解析, 这些解析内容包括如下内容:
		1. 去除FactoryBean的修饰符, 也就是如果name="$aa", 那么会首先去除&而使name="aa".
		2. 取指定alias所表示的最终beanName, 例如别名A指向名称为B的bean则返回B;若别名A只想别名B, 别名B又指向名称为C的bean则返回C.
		*/
		final String beanName = transformedBeanName(name);
		Object bean;

		/* 
		(二). 尝试从缓存中加载单例.
		单例在Spring的同一个容器内只会被创建一次, 后续再获取bean, 就直接从单例缓存中获取了. 当然这里也只是尝试加载, 首先尝试从缓存中加载, 如果加载不成功则再次尝试从singleFactories中加载, 因为再创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,再Spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中, 一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory
		*/
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
      /*
      (三). bean的实例化
      如果从缓存中得到了bean的原始状态, 则需要对bean进行实例化.缓存中记录的只是最原始的bean状态, 并不一定是我们最终想要的bean. 举个例子吗加入我们需要对工厂bean进行处理, 那么这里得到的其实是工厂bean的初始状态, 但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean, 而getObjectForBeanInstance就是完成这个工作的.
      */
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
      /*
      (四). 原型模式的依赖检查
      只有在单例情况下才会尝试解决循环依赖, 原型模式情况下, 如果存在A中又B的属性, B中有A的属性, 那么当依赖注入的时候, 就会产生当A还未创建完的时候因为对于B的创建再次返回创建A, 造成循环依赖. 也就是isPrototypeCurrentlyInCreation(beanName)判断true
      */
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			/*
			(五). 检查parentBeanFactory
			从代码上看, 如果缓存没有数据的话直接转到父类工厂上去加载了, 这是为什么呢?
			可能读者忽略了一个很重要的判断条件: parentBeanFactory != null && !containsBeanDefinition(beanName). parentBeanFactory != null. parentBeanFactory如果为空, 则其他一切都是浮云, 这个没什么说的, 但是!containsBeanDefinition(beanName)就比较重要了, 它是在检测如果当前加载的XML配置文件中不包含beanName所对应的配置, 就只能到parentBeanFactory去尝试下了, 然后递归的调用getBean方法.
			*/
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
        /*
        (六). 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition.
        因为从XML配置文件中读取到的Bean信息是存储在GernericBeanDefinition中的, 但是所有的Bean的后续处理都是针对于RootBeanDefinition的, 所以这里需要进行一个转换, 转换的同时如果父类bean不为空的话, 则会一并合并父类的属性.
        */
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				/*
				(七). 寻找依赖
				因为bean的初始化过程很可能会用到某些属性, 而某些属性很可能是动态配置的, 并且配置成依赖与其他的bean, 那么这个时候就有必要先加载依赖的bean, 所以, 在Spring的加载顺序中, 在初始化某一个bean的时候首先会初始化这个bean所对应的依赖.
				*/
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				/*
				(八). 针对不同的scope进行bean的创建
				我们都知道, 在Spring中存在不同的scope, 其中默认的是singleton, 但是还有其他的配置诸如prototype, request之类的. 在这个步骤中, Spring会根据不同的配置进行不同的初始化策略.
				*/
				if (mbd.isSingleton()) {
					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;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		/*
		(九). 类型转换
		程序到这里返回bean后基本结束了, 通常对该方法的调用参数requiredType是为空的, 但是可能会存在这样的情况, 返回的bean其实是个String, 但是requiredType却传入Integer类型, 那么这时候本步骤就会起作用了, 它的功能是将返回的bean转换为requiredType所指定的类型.当然, String转换为Integer是最简单的一种转换, 在Spring中提供了各种各样的转换器, 用户也可以自己扩展转换器来满足需求.
		经过上面的步骤后bean的加载就结束了, 这个时候就可以返回我们所需要的bean了, 其中最重要的步骤8, 针对不同的scope进行bean的创建, 你会看到各种常用的Spring特性在这里的实现.
		*/
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

复制代码

5.1 FactoryBean的使用

一般情况下, Spring通过反射机制利用bean的class属性指定实现类来实例化bean. 在某些情况下, 实例化bean过程比较复杂, 如果按照传统的方式, 则需要在<bean>中提供大量的配置信息, 配置方式的灵活性是受限的, 这是采用编码的方式可能会得到一个简单的方案. Spring为此提供了一个 org.springframework.bean.factory.FactoryBean 的工厂类接口, 用户可以通过实现该接口定制实例化bean的逻辑.

FactoryBean接口对于Spring框架来说占有重要的地位, Spring本身就提供了70多个FactoryBean的实现. 它们隐藏了实例化一些复杂bean的细节, 给上层应用带来了便利. 从Spring3.0开始, FactoryBean开始支持泛型, 即接口声明改为FactoryBean<T>的形式:
复制代码
public interface FactoryBean<T> {
    T getObject() throws Exception;
    Class<?> getObjectType();
    default boolean isSingleton() {
      return true;
    }
  }
复制代码

在该接口中还定义了3个方法:

T getObject()
boolean isSingleton()
Class<?> getObjectType()

当配置文件中的class属性配置的实现类是FactoryBean时, 通过getBean()方法返回的不是FactoryBean本身, 而是FactoryBean#getObject()方法所返回的对象, 相当于FactoryBean#getObject()代理了getBean()方法.

5.2 缓存中获取单例Bean

介绍过FactoryBean的用法后, 我们就可以了解bean加载的过程了. 前面已经提到过, 单例在Spring的同一个容器内只会被创建一次, 后续再获取bena直接从单例缓存中获取, 当然这里也是只尝试加载, 首先尝试从缓存中加载, 然后再次尝试从singletonFactories中加载. 因为再创建单例bean的时候会存在依赖注入的情况, 而在创建依赖的时候为了避免循环依赖, Spring创建bean的原则是不等bean创建完成就会将查u你感觉爱你bean的ObjectFactory提早曝光加到缓存中, 一旦下一个bean创建时需要依赖上个bean, 则直接使用ObjectFactory.
复制代码
@Override
	public Object getSingleton(String beanName) {
    // 参数true设置标识允许早起依赖
		return getSingleton(beanName, true);
	}

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 检查缓存中是否存在实例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      // 如果为空, 则锁定全局变量并进行处理
			synchronized (this.singletonObjects) {
        // 如果此bean正在加载则不处理
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
          // 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
            // 调用预先设定的getObject方法
						singletonObject = singletonFactory.getObject();
            // 记录再缓存中, earlySingletonObjects和singletonFactories互斥
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
复制代码

这个方法因为涉及循环依赖的检测, 以及涉及很多变量的记录存取, 所以让很多读者摸不着头脑. 这个方法首先尝试从singletonObjects里面获取实例, 如果获取不到, 在尝试从singletonFactories里面获取beanName对应的ObjectFactory, 然后调用这个ObjectFactory的getObject来创建bean, 并放到earlySingletonObjects里面去, 并且从singletonFactories里面remove掉这个ObjectFactory, 而对于后续的所有内存操作都只为了循环依赖检测时候使用, 也就是在allowEarlyReference为true的情况下才会使用.

这里涉及用户存储bean的不同mao, 简单解释如下.

  • singletonObjects: 用户保存BeanName和创建bean实例之间的关系, bean name —> bean instance.
  • singletonFactoriesL用于保存BeanName和创建bean的工厂之间的关系, bean name —> ObjectFactory.
  • earlySingletonObjects: 也是保存BeanName 和创建bean实例之间的关系, 与singletonObjects不同之处在于, 当一个单例bean被放到这里面后, 那么当bean还在创建过程中, 就可以通过getBean方法获取到了, 其目的是用来检测循环引用.
  • registeredSingletons: 用来保存当前所有已注册的bean.

5.3 从bean的实例中获取对象

在getBean方法中, getObejctForBeanInstance是个高频率使用的方法, 无论是从缓存中获得bean还是根据不同的scope策略加载bean. 总之, 我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性, 其实就是用于检测当前bean是否是FactoryBean类型的bean, 如果是, 那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值.

无论是从缓存中获取到的bean还是通过不同的scope策略加载的bean都只是最原始的bean状态, 并不一定是我们最终想要的bean. 举个例子, 加入我们需要对工厂bean进行处理, 那么这里得到的其实是工厂bean的初始状态, 但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean, 而getObjectForBeanInstance方法就是完成这个工作的.
复制代码

org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// 现在我们有了个bean的实例, 这个实例可能会是正常的bean或者是FactoryBean
    // 如果是FactoryBean我们使用它创建实例, 但是如果用户想要直接获取工厂实例而不是工厂的getObject方法对应的实例那么传入的name应该加入前缀&
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

    // 加载FactoryBean
		Object object = null;
		if (mbd == null) {
      // 尝试从缓存中加载bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 到这里已经明确知道beanInstance一定是FactoryBean类型
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是否定义beanName
			if (mbd == null && containsBeanDefinition(beanName)) {
        // 将存储再XML配置文件的GenericBeanDefinition转换为RootBeanDefinition, 如果指定BeanName是子Bean的话同时会合并父类的相关属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
      // 是否是用户定义的而不是应用程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
复制代码

从上面代码来看, 其实这个方法并没有什么重要的信息, 大多是些辅助代码以及一些功能性的判断, 而真正的核心代码却委托给了getObjectFromFactoryBean, 我们来看看getObjectFromBeanInstance中所做的工作.

  1. 对FactoryBean正确性的验证
  2. 对非FactoryBean不做任何处理
  3. 对bean进行转换
  4. 将从Factory中解析bean的工作委托给getObjectFromFactoryBean.

org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
          // 调用ObjectFactory的后置处理器
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}


	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
      // 需要权限验证
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
        // 直接调用getObject方法
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

复制代码

5.4 获取单例

如果缓存中不存在已经加载的单例bean就需要从头开始bean的加载过程了, 而Spring中使用了getSingleton的重载方法实现bean的加载过程.

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
    // 全局变量需要同步
		synchronized (this.singletonObjects) {
      // 首先检查对应的bean是否已经加载过, 因为singleton模式其实就是复用以创建的bean, 所以这一步时必须的
			Object singletonObject = this.singletonObjects.get(beanName);
      // 如果为空才可以进行singleton的初始化
			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 + "'");
				}
        // 记录加载状态, 也就是通过this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中, 这样便可以对循环依赖进行检测.
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<Exception>();
				}
				try {
          // 初始化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.
					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 != NULL_OBJECT ? singletonObject : null);
		}
	}

复制代码

上述代码中其实是使用了回调方法, 使得程序可以在单例创建的前后做一些准备及处理操作, 而真正的获取单例的bean的方法其实并不是在此方法中实现的, 其实现逻辑是在ObjectFactory类型的实例singletonFactory中实现的. 而这些准备及处理操作包括如下内容:

  1. 检查缓存是否已经加载过
  2. 若没有加载, 则记录beanName的正在加载状态
  3. 加载单例前记录加载状态

可能你会觉得beforeSingletonCreation方法是个空实现, 里面没有任何逻辑, 但其实不是. 这个函数中做了一个很重要的操作: 记录加载状态, 也就是通过this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中, 这样便可以对循环依赖进行检测.

protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

复制代码
  1. 通过调用参数传入的ObjectFactory的个体Object方法实例化bean.
  2. 加载单例后的处理方法调用.

同步骤(3)的记录加载状态相似, 当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录.

protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}

复制代码
  1. 将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态.

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

复制代码
  1. 返回处理结果

虽然我们已经从外部了解了加载bean的逻辑架构, 但现在我们还没有开始对bean加载功能的探索, 之前提到过, bena的加载逻辑其实是在传入的ObjectFactory类型的参数singletonFatory中定义的, 我们反推参数的获取, 得到如下代码

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							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;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

复制代码

ObjectFactory的核心部分其实只是调用了createBean的方法, 所以还需要到createBean方法中寻找.

5.5 准备创建Bean

我们不可能指望在一个函数中完成一个复杂的逻辑, 而且我们跟踪了这么多Spring代码, 经历了这么多函数, 或多或少也发现了一些规律: 一个真正干活的函数其实是以do开头的, 比如doGetObjectFromFactoryBean; 而给我们错觉的函数getObjectFromFactoryBean, 其实只是从全局角度去做些统筹的工作. 这个规则对于createBean也不例外, 那么我们看看在createBean函数中做了那些准备工作.

org.springframework.beans.factory.support.AbstractBeanFactory#createBean

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, 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.
    // 锁定class, 根据设置的class属性或者根据className来解析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);
		}

		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}


复制代码

从代码中我们可以总结出函数完成的具体步骤及功能.

  1. 根据设置的class属性或者根据className来解析Class.
  2. 对override属性进行标记及验证.

很多读者可能会不知道这个方法的作用, 因为再Spring的配置里面根本就没有诸如override-method之类的配置, 那么这个方法到底是干什么用的呢?

其实在Spring中确实没有override-method这样的配置, 但是如果读过前面的部分, 可能会有所发现, 在Spring配置中存在lookup-method和replace-method的, 而这两个配置的加载其实就是将配置统一存放在BeanDefinition中methodOverrides属性里, 而这个函数的操作其实也就是针对于这两个配置的.

  1. 应用初始化前的后处理器, 解析指定bean是否存在初始化前的短路操作.
  2. 创建bean.

我们首先查看下对override属性标记及验证的逻辑实现.

5.5.1 处理 override 属性

查看源码中 AbstractBeanDefinition 类的 prepareMethodOverrides 方法:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
		// Check that lookup methods exists.
		MethodOverrides methodOverrides = getMethodOverrides();
		if (!methodOverrides.isEmpty()) {
			Set<MethodOverride> overrides = methodOverrides.getOverrides();
			synchronized (overrides) {
				for (MethodOverride mo : overrides) {
					prepareMethodOverride(mo);
				}
			}
		}
	}

	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() + "]");
		}
		else if (count == 1) {
			// Mark override as not overloaded, to avoid the overhead of arg type checking.
			mo.setOverloaded(false);
		}
	}

复制代码

之前反复提到过, 在Spring配置中存在 lookup-method 和 replace-method 两个配置功能, 而这两个配置的加载其实就是将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里, 这两个功能实现原理其实是在 bean 实例化的时候如果检测到存在 methodOverrides 属性, 会动态地为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理, 相关逻辑实现在 bean 的实例化部分详细介绍.

对于方法的匹配来讲, 如果一个类总存在若干个重载方法, 那么在函数调用及增强的时候还需要根据参数类型进行匹配, 来最终确认当前调用的到底是哪个函数. 但是Spring将一部分匹配工作在这里完成了, 如果当前类中的方法只有一个, 那么就设置该方法没有被重载, 这样在后续调用的时候就可以直接使用找到的方法, 而不需要进行方法的参数匹配验证了, 而且还可以提前对方法存在性进行验证.

5.5.2 实例化的前置处理

在真正调用 doCreate 方法创建 bean 的实例前使用了这样一个方法 resolveBeforeInstantiation(beanName, mdb) 对 BeanDefinigiton 中的属性做些前置处理. 当然, 无论其中是否有相应的逻辑实现我们都可以理解, 因为真正逻辑实现前后留有处理函数也是可扩展的一种提现, 但是, 这并不是最重要的, 在函数中还提供了一个短路判断, 这才是最为关键的部分.

if (bean != null) {
  return bean;
}

复制代码

当经过前置处理后返回的结果如果不为空, 那么会直接略过后续的 Bean 的创建而直接返回结果. 这一特性虽然很容易被忽略, 但是却起着至关重要的作用, 我们熟知的AOP功能就是基于这里的判断的.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// 如果尚未被解析
			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;
	}

复制代码

此方法中最吸引我们的无疑是两个方法 applyBeanPostProcessorsBeforeInstantiation 以及 applyBeanPostProcessorsAfterInitialization . 两个方法实现的非常简单, 无非是对后处理器中的所有 InstantiationAwareBeanPostProcessor 类型的后处理器进行 postProcessAfterInstantiation 方法和 BeanPostProcessor 的 postProcessAfterInitialization 方法的调用.

  1. 实例化前的后处理器应用

bean的实例化前调用, 也就是将 AbstractBeanDefinition 转换为 BeanWrapper 前的处理. 给子类一个修改 BeanDefinition 的机会, 也就是说当程序经过这个方法后, bean可能已经不是我们认为的 bean 了, 而是或许成为了一个经过处理的代理 bean, 可能是通过 cglib 生成的, 也可能是通过其他技术生成的,

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

复制代码
  1. 实例化后的后处理器应用

在讲解从缓存中获取单例 bean 的时候就提到过, Spring 中的规则是在 bean 的初始化后尽可能保证将注册的后处理器的 postProcessAfterInstantiation 方法应用到该 bean 中, 因为如果返回的 bean 不为空, 那么便不会再次经理普通bean的创建过程, 所以只能在这里应用后处理器的 postProcessAfterInstantiation 方法.

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessAfterInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

复制代码

5.6 循环依赖

实例化bean是一个非常复杂的过程, 而其中最比较难以理解的就是对循环依赖的解决.

5.6.1 什么是循环依赖

循环依赖就是循环引用, 就是两个或多个 bean 相互之间持有对方, 比如 CircleA 引用 CricleB, CircleB 引用 CircleC, CricleC引用 CircleA, 则它们最终反应为一个环. 此处不是循环调用, 循环调用是方法之间的循环调用.

循环调用是无法解决的, 除非有终结条件, 否则就是死循环, 最终导致内存溢出错误.

5.6.2 Spring 如何解决循环依赖

Spring 容器循环依赖包括构造器循环依赖和setter循环依赖, 那Spring容器如何解决循环依赖呢?

在Spring中将循环依赖处理分成了3中情况.

  1. 构造器循环依赖

表示通过构造器注入构成的循环依赖, 此依赖时无法解决的, 只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖.

如在创建 TestA 类时, 构造器需要 TestB 类, 那将去创建 TestB, 在创建 TestB 类时又发现需要 TestC 类, 则又去创建 TestC, 最终在创建 TestC 时发现有需要 TestA, 从而形成了一个环, 没办法创建.

Spring 容器将每一个正在创建的 bean 标识符放在一个 "当前创建bean池" 中, bean 标识符在创建过程中将一直保持在这个池中, 因此如果在创建 bean 过程中发现自己已经在 "当前创建bean池" 里时, 将抛出 BeanCurrentlyInCreationException异常表示循环依赖; 而对于创建完毕的 bean 将从 "当前创建bean池" 里清楚掉.

  1. setter 循环依赖

表示通过setter注入方式构成循环依赖. 对于setter 注入造成的依赖是通过 Spring 容器提前暴露刚完成构造器注入但未完成其他步骤(如 setter 注入)的 bean 来完成的, 而且只能解决单例作用域的 bean 循环依赖. 通过提前暴露一个单例工厂方法, 从而使其他 bean 能引用到该 bean, 如下代码所示:

addSingletonFactory(beanName, new ObjectFactory() {
  public Object getObject() throws BeanException {
    return getEarlyBeanReference(beanName, mbd, bean);
  }
});

复制代码

​ 具体步骤如下.

​ (1). Spring 容器创建单例 "testA" bean, 首先根据无参构造器创建bean, 并暴露一个 "ObjectFactory" 用于返回一个提起暴露一个创建中的 bean, 并将 "testA" 标识符放到 "当前创建bena池" , 然后进行 setter 注入 "testB".

​ (2). Spring 容器创建单例 "testB" bean, 首先根据无参构造器创建bean, 并暴露一个 "ObjectFactory" 用于返回一个提起暴露一个创建中的 bean, 并将 "testB" 标识符放到 "当前创建bena池" , 然后进行 setter 注入 "testC".

​ (3). Spring 容器创建单例 "testC" bean, 首先根据无参构造器创建bean, 并暴露一个 "ObjectFactory" 用于返回一个提起暴露一个创建中的 bean, 并将 "testC" 标识符放到 "当前创建bena池" , 然后进行 setter 注入 "circle". 进行注入 "testA" 时由于提前暴露了 "ObjectFactory" 工厂, 从而使用它返回提前暴露一个创建中的 bean.

​ (4). 最后在依赖注入 "testB" 和 "testA", 完成 setter 注入

  1. prototype范围的依赖处理

对于 "prototype" 作用域 bean, Spring 容器无法完成依赖注入, 因为Spring 容器不进行缓存 "prototype" 作用域的 bean, 因此无法提前暴露一个创建中的 bean.

对于 "singleton" 作用域 bean, 可以通过 "setAllowCircularReferences(false)"; 来禁用循环引用.

5.7 创建 bean

介绍了循环依赖以及Spring中循环依赖的处理方式后, 继续4,5小节的内容. 当经历过 resolveBeforeInstantiation 方法后, 程序有两个选择, 如果创建了代理或者说重写了 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法并在方法 postProcessBeforeInstantiation 中改变了 bean, 则直接返回就可以了, 否则需要进行常规 bean 的创建. 而这常规 bean 的创建就是在 doCreateBean 中完成的.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

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

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

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
          // 应用 MergedBeanDefinitionPostProcessor
					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.
    /*
    是否需要提早曝光: 单例&允许循环依赖&当前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");
			}
      // 为避免后期循环依赖, 可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
          // 对 bean 再一次依赖引用, 主要应用 SmartInstantiationAware BeanPostProcessor, 其中我们熟悉的AOP就是在这里将advice动态织入bean中, 若没有则直接返回bean, 不做任何处理
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
      // 对bean进行填充, 将各个属性值注入, 其中可能存在依赖于其他bean的属性, 则会递归初始依赖bean
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
       // 调用初始化方法, 比如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);
			}
		}

		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<String>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
            // 检测依赖 
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
          /*
          因为bean创建后其所依赖的bean一定是已经创建的, 
          actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有没全部创建完, 也就会说存在循环依赖
          */
					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 {
      // 根据scope注册bean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

复制代码

尽管日志与异常的内容非常重要, 但是在阅读源码的时候似乎大部分人都会直接忽略掉. 在此不深入探讨日志及异常的设计, 我们看看整个函数的概要思路.

  1. 如果是单例则需要首先清除缓存.
  2. 实例化bean, 将 BeanDefinition 转换为 BeanWrapper.

转换是一个复杂的过程, 但是我们可以尝试概括大致的功能, 如下所示.

  • 如果存在工厂方法则使用工厂方法进行初始化
  • 一个类有多个构造函数, 每个构造函数都有不同的参数, 所以需要根据参数锁定构造函数并进行初始化.
  • 如果既不存在工厂方法也不存在带有参数的构造函数, 则使用默认的构造函数进行bean的实例化.
  1. MergedBeanDefinitionPostProcessor 的应用.

bean 合并后的处理, Autowired注解正式通过此方法实现注入类型的预解析.

  1. 依赖处理

在Spring 中会有循环依赖的情况, 例如, 当A中含有B的属性, 而B中又含有A的属性时就会构成一个循环依赖, 此时如果A和B都是单例, 那么在Spring中处理方式就是当创建B的时候, 实际自动注入A的步骤时, 并不是直接去再次创建A, 而是通过放入缓存中的ObjectFactory来创建实例, 这样就解决了循环依赖的问题.

  1. 属性填充. 将所有属性填充至bean的实例中.
  2. 循环依赖检查

之前有提到过, 在Spring 中解决循环依赖只对单例有效, 而对于prototype的bean, Spring没有好的解决办法, 唯一要做的就是抛出异常. 在这个步骤里面会检测已经加载的bean是否已经出现了循环依赖, 并判断是否需要抛出异常/

  1. 注册DisposableBean

如果配置了destroy-method, 这里需要注册以便于在销毁时候调用.

  1. 完成创建并返回.

可以看到上面的步骤非常的繁琐, 每一步骤都使用了大量的代码来完成其功能, 最复杂也是最难以理解的当属循环依赖的处理, 在真正进入doCreateBean前我们有必要先了解循环依赖.

5.7.1 创建Bean的实例

当我们了解了循环以来以后就可以深入分析创建bean的每个步骤了, 首先我们从createBeanInstance开始,

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		// Make sure bean class is actually resolved at this point.
    // 解析class
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

    // 如果工厂方法不为空则使用工厂方法初始化策略
		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
        // 一个类有多个构造函数, 每个构造函数都有不同的参数, 所以调用前需要先根据参数锁定构造函数或对应的工厂方法
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
    // 如果已经解析过则使用解析好的构造函数方法不需要再次锁定
		if (resolved) {
			if (autowireNecessary) {
        // 构造函数自动注入
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
        // 使用默认构造函数
				return instantiateBean(beanName, mbd);
			}
		}

		// Need to determine the constructor...
    // 需要根据参数解析构造函数
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      // 构造函数自动注入
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// No special handling: simply use no-arg constructor.
    // 使用默认构造函数
		return instantiateBean(beanName, mbd);
	}

复制代码

虽然代码中实例化的细节非常复杂, 但是在 createBeanIntance 方法中我们还是可以清晰的看到实例化的逻辑的.

  1. 如果在 RootBeanDefinition 中存在 factoryMethodName属性, 或者说在配置文件配置了 factory-method, 那么Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据 RootBeanDefinition 中的配置生成 bean 的实例.

  2. 解析构造函数并进行构造函数的实例化. 因为一个bean对应的类中可能会有多个构造函数, 而每个构造函数的参数不同, Spring 在根据参数及类型去判断最终会使用哪个构造函数进行实例化. 但是判断的过程是个比较消耗性能的步骤, 所以采用缓存机制, 如果已经解析过则不需要重复解析而是直接从RootBeanDefinition 中的属性resolvedConstructorOrFactoryMethod 缓存的值去取, 否则需要再次解析, 并将解析的结果添加至 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 中.

    • autowireConstructor

      对于实例的创建 Spring 中分成了两种情况, 一种是通用的实例化, 另一种是带有参数的实例化. 带有参数的实例化过程相当复杂, 因为存在着不确定性, 所以在判断对应参数上做了大量工作.

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor

    protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
      		return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
      	}
    
    public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
    
    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);
    
    Constructor<?> constructorToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;
    
      // explicitArgs 通过getBean方法传入
      // 如果getBean方法调用的时候指定方法参数那么直接使用
    if (explicitArgs != null) {
    	argsToUse = explicitArgs;
    }
    else {
    // 如果getBean方法调用的时候没有指定方法参数则尝试从配置文件中解析
    	Object[] argsToResolve = null;
    // 尝试从缓存中获取
    	synchronized (mbd.constructorArgumentLock) {
    		constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
    		if (constructorToUse != null && mbd.constructorArgumentsResolved) {
        // 从缓存中获取
    			argsToUse = mbd.resolvedConstructorArguments;
    			if (argsToUse == null) {
          // 配置的构造函数参数
    				argsToResolve = mbd.preparedConstructorArguments;
    			}
    		}
    	}
    // 如果缓存中存在
    	if (argsToResolve != null) {
      // 解析参数类型, 如给定方法的构造函数A(int, int) 则通过此方法后就会把配置中("1", "1")转换为 (1, 1)
      // 缓存中的值可能是原始值也可能是最终值
    		argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
    	}
    }
    
      // 没有被缓存
    if (constructorToUse == null) {
    	// Need to resolve the constructor.
    	boolean autowiring = (chosenCtors != null ||
    			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    	ConstructorArgumentValues resolvedValues = null;
    
    	int minNrOfArgs;
    	if (explicitArgs != null) {
    		minNrOfArgs = explicitArgs.length;
    	}
    	else {
      // 提取配置文件中的配置的构造函数参数
    		ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
      // 用于承载解析后的构造函数参数的值
    		resolvedValues = new ConstructorArgumentValues();
      // 能解析到的参数个数
    		minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    	}
    
    	// Take specified constructors, if any.
    	Constructor<?>[] candidates = chosenCtors;
    	if (candidates == null) {
    		Class<?> beanClass = mbd.getBeanClass();
    		try {
    			candidates = (mbd.isNonPublicAccessAllowed() ?
    					beanClass.getDeclaredConstructors() : beanClass.getConstructors());
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    					"Resolution of declared constructors on bean Class [" + beanClass.getName() +
    					"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
    		}
    	}
    
    // 排序给定的构造函数, public构造函数优先参数数量降序, 非public构造函数参数数量降序
    	AutowireUtils.sortConstructors(candidates);
    	int minTypeDiffWeight = Integer.MAX_VALUE;
    	Set<Constructor<?>> ambiguousConstructors = null;
    	LinkedList<UnsatisfiedDependencyException> causes = null;
    
    	for (Constructor<?> candidate : candidates) {
    		Class<?>[] paramTypes = candidate.getParameterTypes();
    
      // 如果已经找到选用的构造函数或者需要的参数个数小于当前的构造函数参数个数则终止, 因为已经按照参数个数降序排列
    		if (constructorToUse != null && argsToUse.length > paramTypes.length) {
    			// Already found greedy constructor that can be satisfied ->
    			// do not look any further, there are only less greedy constructors left.
    			break;
    		}
    		if (paramTypes.length < minNrOfArgs) {
        // 参数个数不相等
    			continue;
    		}
    
    		ArgumentsHolder argsHolder;
    		if (resolvedValues != null) {
        // 有参数则根据值构造对应参数类型的参数
    			try {
          // 注释上获取参数名称
    				String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
    				if (paramNames == null) {
            // 获取参数名称探索器
    					ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
    					if (pnd != null) {
              // 获取指定构造函数的参数名称
    						paramNames = pnd.getParameterNames(candidate);
    					}
    				}
          // 根据名称和数据类型创建参数持有者
    				argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
    						getUserDeclaredConstructor(candidate), autowiring);
    			}
    			catch (UnsatisfiedDependencyException ex) {
    				if (this.beanFactory.logger.isTraceEnabled()) {
    					this.beanFactory.logger.trace(
    							"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
    				}
    				// Swallow and try next constructor.
    				if (causes == null) {
    					causes = new LinkedList<UnsatisfiedDependencyException>();
    				}
    				causes.add(ex);
    				continue;
    			}
    		}
    		else {
    			// Explicit arguments given -> arguments length must match exactly.
    			if (paramTypes.length != explicitArgs.length) {
    				continue;
    			}
        // 构造函数没有参数的情况
    			argsHolder = new ArgumentsHolder(explicitArgs);
    		}
    
      // 探测是否有不确定性的构造函数存在, 例如不同构造函数的参数为父子关系
    		int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
    				argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
    		// Choose this constructor if it represents the closest match.
      // 如果它代表着当前最接近的匹配则选择作为构造函数
    		if (typeDiffWeight < minTypeDiffWeight) {
    			constructorToUse = candidate;
    			argsHolderToUse = argsHolder;
    			argsToUse = argsHolder.arguments;
    			minTypeDiffWeight = typeDiffWeight;
    			ambiguousConstructors = null;
    		}
    		else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
    			if (ambiguousConstructors == null) {
    				ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
    				ambiguousConstructors.add(constructorToUse);
    			}
    			ambiguousConstructors.add(candidate);
    		}
    	}
    
    	if (constructorToUse == null) {
    		if (causes != null) {
    			UnsatisfiedDependencyException ex = causes.removeLast();
    			for (Exception cause : causes) {
    				this.beanFactory.onSuppressedException(cause);
    			}
    			throw ex;
    		}
    		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    				"Could not resolve matching constructor " +
    				"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
    	}
    	else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
    		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    				"Ambiguous constructor matches found in bean '" + beanName + "' " +
    				"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
    				ambiguousConstructors);
    	}
    
    	if (explicitArgs == null) {
      // 将解析的构造函数加入缓存
    		argsHolderToUse.storeCache(mbd, constructorToUse);
    	}
    }
    
    try {
    	Object beanInstance;
    
    	if (System.getSecurityManager() != null) {
    		final Constructor<?> ctorToUse = constructorToUse;
    		final Object[] argumentsToUse = argsToUse;
    		beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
    			@Override
    			public Object run() {
    				return beanFactory.getInstantiationStrategy().instantiate(
    						mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
    			}
    		}, beanFactory.getAccessControlContext());
    	}
    	else {
    		beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
    				mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
    	}
    
    // 将构建的实例加入BeanWrapper中
      			bw.setBeanInstance(beanInstance);
      			return bw;
      		}
      		catch (Throwable ex) {
      			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
      					"Bean instantiation via constructor failed", ex);
      		}
      	}
    
    复制代码
    逻辑很复杂, 函数代码量很大, 我们总览一下整个函数, 其实现的功能考虑了一下几个方面.
    
    1. 构造函数参数的确定.
    
       - 根据 explicitArgs 参数判断
    
         如果传入的参数 explicitArgs 不为空, 那么可以直接确定参数, 因为 explicitArgs 参数是在调用 Bean 的时候用户指定的, 在 BeanFactory 类中存在这样的方法:
    
         ```java
         Object getBean(String name, Object ... args) throws BeansException;
         ```
    
         在获取 bean 的时候, 用户不但可以指定 bean 的名称还可以指定 bean 所对应类的构造函数或者工厂方法的方法参数, 主要用于静态工厂方法的调用, 而这里是需要给定完全匹配的参数的, 所以, 便可以判断, 如果传入参数 explicitArgs 不为空, 则可以确定构造函数参数就是它.
    
       - 缓存中获取
    
         除此之外, 确定参数的办法如果之前已经分析过, 也就是说构造函数参数已经记录在缓存中, 那么便可以直接拿来使用. 而且, 这里要提到的是, 在缓存中缓存的可能是参数的最终类型也可能是参数的初始类型, 例如: 构造函数参数要求的是int类型, 但是原始的参数值可能是String 类型的 "1", 那么即使在缓存中得到了参数, 也需要经过类型转换器的过滤以确保参数类型与对应的构造函数参数类型完全对应.
    
       - 配置文件中获取
    
         如果不能根据传入的参数 explicitArgs 确定构造函数的参数也无法在缓存中达到相关信息, 那么只能开始新一轮的分析了.
    
         分析从获取配置文件中配置的构造函数信息开始, 经过之前的分析, 我们知道, Spring中配置文件中的信息经过转化都会通过 BeanDefinition 实例承载, 也就是参数 mbd 中包含, 那么可以通过调用 mbd.getConstructorArgumentValues() 参数获取配置的构造函数信息. 有了配置中的信息便可以获取对应的参数值信息了, 获取参数值的信息包括直接指定值, 如: 直接指定构造函数中某个值为原始类型 String 类型, 或者是一个对其他 bean 的引用, 而这一处理委托给 resolveConstructorArguments 方法, 并返回能解析到的参数的个数.
    
    2. 构造函数的确定
    
       经过了第一步后已经确定了构造函数的参数, 接下来的任务就是根据构造函数参数在所有构造函数中锁定对应的构造函数, 而匹配的方法就是根据参数个数匹配, 所以在匹配之前需要先对构造函数按照 public 构造函数优先参数数量降序, 非public构造函数参数数量降序. 这样可以在便利的情况下迅速判断排在后面的构造函数参数个数是否符合条件.
    
       由于在配置文件中并不是唯一限制使用参数位置索引的方式去创建, 同样还支持指定参数名称进行设定参数值的情况, 如<constructor-arg name="aa">, 那么这种情况就需要首先确定构造函数中的参数名称.
    
       获取参数名称可以有两种方式, 一种时通过注解的方式直接获取, 另一种就是使用Spirng中提供的 工具 类 ParameterNameDiscoverer 来获取. 构造函数, 参数名称, 参数类型, 参数值都确定后就可以锁定构造函数以及转换对应的参数类型了.
    
    3. 根据确定的构造函数转换对应的参数类型
    
       主要是使用Spring 中提供的类型转换器或者用户提供的自定义类型转换器进行转换.
    
    4. 构造函数不确定性的验证
    
       当然, 有时候即使构造函数, 参数名称, 参数类型, 参数值都确定后也不一定会直接锁定构造函数, 不同构造函数的参数为父子关系, 所以Spring 在最后又做了一次验证.
    
    5. 根据实例化策略以及得到的构造函数及构造函数参数实例化Bean. 
    
    复制代码
    • instantiateBean

      经历了带有参数的构造函数的实例构造, 相信你会轻松愉快的理解不带参数的构造函数的实例化过程.

      org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean

      protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
      		try {
      			Object beanInstance;
      			final BeanFactory parent = this;
      			if (System.getSecurityManager() != null) {
      				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
      						getInstantiationStrategy().instantiate(mbd, beanName, parent),
      						getAccessControlContext());
      			}
      			else {
      				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      			}
      			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      			initBeanWrapper(bw);
      			return bw;
      		}
      		catch (Throwable ex) {
      			throw new BeanCreationException(
      					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
      		}
      	}
      
      复制代码

      此方法并没有实质性的逻辑, 带有参数的实例构造中, Spring 把经理都放在了构造函数以及参数的匹配上, 所以如果没有参数的话那将是非常简单的一件事, 直接调用实例化策略进行实例化就可以了.

    • 实例化策略

      实例化过程中反复提到过实例化策略, 那这又是做什么用的呢? 其实, 经过前面的分析, 我们已经得到了足以实例化的所有相关信息, 完全可以使用最简单的反射方法直接反射来构造实例对象, 但是Spring却并没有这么做.

      org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)

      @Override
      	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
      		// Don't override the class with CGLIB if no overrides.
          // 如果有需要覆盖或者动态替换的方法则当然需要使用cglib进行动态代理, 因为可以在创建代理的同时将动态方法织入类中, 但是如果没有需要动态代理改变的方法, 为了方便直接反射就可以了
      		if (!bd.hasMethodOverrides()) {
      			Constructor<?> constructorToUse;
      			synchronized (bd.constructorArgumentLock) {
      				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
      				if (constructorToUse == null) {
      					final Class<?> clazz = bd.getBeanClass();
      					if (clazz.isInterface()) {
      						throw new BeanInstantiationException(clazz, "Specified class is an interface");
      					}
      					try {
      						if (System.getSecurityManager() != null) {
      							constructorToUse = AccessController.doPrivileged(
      									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
      						}
      						else {
      							constructorToUse = clazz.getDeclaredConstructor();
      						}
      						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
      					}
      					catch (Throwable ex) {
      						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
      					}
      				}
      			}
      			return BeanUtils.instantiateClass(constructorToUse);
      		}
      		else {
      			// Must generate CGLIB subclass.
      			return instantiateWithMethodInjection(bd, beanName, owner);
      		}
      	}
      
      复制代码

      看了上面两个函数后似乎我们已经感受到了 Spring 的良苦用心以及为了能更方便的使用 Spring 而做了大量的工作. 程序中, 首先判断如果 beanDefinition.getMethodOverrides() 为空也就是用户没有使用 replace 或者 lookup 的配置方法, 那么直接使用放射的方式, 简单快捷, 但是如果使用了这两个特性, 在直接使用反射的方式创建实例就不妥了, 因为需要将这两个配置提供的功能切入进去, 所以就必须要使用动态代理的方式将包含两个特性所对应的逻辑的拦截增强器设置进去, 这样才可以保证在调用方法的时候会被相应的拦截器增强, 返回值为包含拦截器的代理实例.

5.7.2 记录创建bean的ObjectFactory

在 doCreate 函数中有这样一段代码:

/*
     	是否需要提早曝光: 单例&允许循环依赖&当前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");
 			}
			// 为避免后期循环依赖, 可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
 			addSingletonFactory(beanName, new ObjectFactory<Object>() {
 				@Override
 				public Object getObject() throws BeansException {
 					// 对 bean 再一次依赖引用, 主要应用 SmartInstantiationAware BeanPostProcessor, 其中我们熟悉的AOP就是在这里将advice动态织入bean中, 若没有则直接返回bean, 不做任何处理
 					return getEarlyBeanReference(beanName, mbd, bean);
 				}
 			});
 		}

复制代码

这段代码不是很复杂, 但是很多人不是太理解这段代码的作用, 而且, 这段代码仅从此函数中去理解也很难弄懂其中的含义, 我们需要从全局的角度去思考 Spring 的依赖解决办法.

  • earlySingletonExposure: 从字面的意思就是提早曝光的单例, 我们暂不定义它的学名叫什么, 我们感兴趣的是有哪些条件影响这个值.

  • mbd.isSingleton(): 没有太多可以解释的, 此 RootBeanDefinition 代表的是否是单例.

  • this.allowCircularReferences: 是否允许循环依赖, 很抱歉, 并没有找到在配置文件中如何配置, 但是在 AbstractRefreshableApplicationContext 中提供了设置函数, 可以通过硬编码的方式进行设置或者可以通过自定义命名空间进行配置, 其中硬编码的方式代码如下:

    ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext("aspectTest.xml");
    bf.setAllowBeanDefinitionOverriding(false);
    
    复制代码
  • isSingletonCurrentlyCreation(beanName): 该 bean 是否在创建中, 在 Spring 中, 会有个专门的属性默认为 DefaultSingletonBeanRegistry 的 singletonsCurrentlyInCreation 来记录bean的加载状态, 在bean开始创建前会将 beanName 记录在属性中, 在 bean 创建结束后会将 beanName 从属性中移除, 那么我们跟随代码一路走来可是对这个属性记录并没有多少印象, 这个状态是在哪里记录的呢? 不同 scope 的记录位置并不一样, 我们以 singleton 为例, 在 singleton 下记录属性的函数是在 DefaultSingletonBeanRegistry 类的 public Object getSingleton(String beanName, ObjectFactory singletonFactory) 函数的 beforeSingletonCreation(beanName) 和 afterSingletonCreation(beanName) 中, 在这两段函数中分别 this.singletonsCurrentlyInCreation.add(beanName) 与this.singletonsCurrentlyInCreation.remove(beanName) 来进行状态的记录与移除.

经过以上分析我们了解变量 earlySingletonExposure 是否单例, 是否允许循环依赖, 是否对应的 bean 正在创建的 条件的综合. 当这3个条件都满足时会执行 addSingletonFactory 操作, 那么加入SingletonFactory 的作用是什么呢? 又是在什么时候调用的呢?

我们还是以最简单AB循环依赖为例, 类A中含有属性类B, 而类B中又会含有属性类A, 那么初始化beanA的过程如图所示:

graph TD
		创建beanA-->开始创建bean记录beanNameA
		subgraph A
		开始创建bean记录beanNameA-->addSingletonFactoryA(addSingletonFactory)
		addSingletonFactoryA(addSingletonFactory)-->populateBean填充A属性
		populateBean填充A属性-->结束创建bean移除beanNameA
		end
		
		subgraph B
		populateBean填充A属性-->开始创建bean记录beanNameB
		开始创建bean记录beanNameB-->addSingletonFactoryB(addSingletonFactory)
		addSingletonFactoryB(addSingletonFactory)-->populateBean填充B属性
		populateBean填充B属性-->结束创建bean移除beanNameB
		end
		
		subgraph C
		populateBean填充B属性-->getBeanA
		end
复制代码

上图展示了创建beanA的流程, 从图中我们看到, 在创建A的时候首先会记录类A所对应的beanName, 并将beanA的创建工厂加入缓存中, 而在对A的属性填充也就是调用populate方法的时候又会再一次的对B进行递归创建, 同样的, 因为在B中同样存在A属性, 因此在实例化B的pupulate方法中优惠再次的初始化B, 也就是图形的最后, 调用getBean(A), 关键是在这里, 在这个函数中并不是直接去实例化A, 而是先去检查缓存中是否有已经创建号的对应的bean, 或者是否已经创建好的ObjectFactory, 而此时对于A的ObjectFactory我们早已创建, 所以便不会再去向后执行, 而是直接调用ObjectFactory去创建A. 这里最关键的是 ObjectFactory 的实现.

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");
 			}
 			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 		}
     
     	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
     		Object exposedObject = bean;
     		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
     			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
     					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
     					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
     				}
     			}
     		}
     		return exposedObject;
     	}

复制代码

在 getEarlyBeanReference 函数中并没有太多的逻辑处理, 或者说除了后处理器的调用外, 没有别的处理工作, 根据以上分析, 基本可以理清 Spring 处理循环依赖的解决办法, 在B中创建依赖A时通过ObjectFactory提供的实例方法来中断A中的属性填充, 使B中持有的A仅仅是刚刚初始化并没有填充任何属性的A, 而这正初始化A的步骤还是在最开始创建A的时候进行的, 但是因为A与B中的A所表示的属性地址是一样的, 所以在A中创建好的属性填充自然可以通过B中的A获取, 这样就解决了循环依赖的问题.

5.7.3 属性注入

在了解循环依赖的时候, 我们曾经反复提到了 populateBean 这个函数, 也多少了解了这个函数的主要功能就是属性填充, 那么究竟是如何实现填充的呢?

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
     		if (bw == null) {
     			if (mbd.hasPropertyValues()) {
     				throw new BeanCreationException(
     						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
     			}
     			else {
     				// 没有可填充的属性
     				return;
     			}
     		}
     
     		// 给 InstantiationAwareBeanPostProcessors 最后一次机会在属性设置前来改变 bean
     		// 如: 可以用来支持属性注入的类型
     		boolean continueWithPropertyPopulation = true;
     
     		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
     			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     				if (bp instanceof InstantiationAwareBeanPostProcessor) {
     					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
              // 返回值为是否继续填充bean 
     					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
     						continueWithPropertyPopulation = false;
     						break;
     					}
     				}
     			}
     		}
     
         // 如果后处理器发出停止填充命令则终止后续的进行
     		if (!continueWithPropertyPopulation) {
     			return;
     		}
     
     		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
     
     		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
     			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
     			// 根据名称自动注入
     			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
     				autowireByName(beanName, mbd, bw, newPvs);
     			}
     			// 根据类型自动注入
     			if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
     				autowireByType(beanName, mbd, bw, newPvs);
     			}
     			pvs = newPvs;
     		}
     
         // 后处理器已经初始化
     		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
         // 需要依赖检查
     		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
     
     		PropertyDescriptor[] filteredPds = null;
     		if (hasInstAwareBpps) {
     			if (pvs == null) {
     				pvs = mbd.getPropertyValues();
     			}
     			for (BeanPostProcessor bp : getBeanPostProcessors()) {
     				if (bp instanceof InstantiationAwareBeanPostProcessor) {
     					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
              // 对所有需要依赖检查的属性进行后置处理
     					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
     					if (pvsToUse == null) {
     						if (filteredPds == null) {
     							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
     						}
     						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
     						if (pvsToUse == null) {
     							return;
     						}
     					}
     					pvs = pvsToUse;
     				}
     			}
     		}
     		if (needsDepCheck) {
     			if (filteredPds == null) {
            // 依赖检查, 对应 depends-on 属性, 3.0已经弃用此属性  
     				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
     			}
     			checkDependencies(beanName, mbd, filteredPds, pvs);
     		}
     
     		if (pvs != null) {
          // 将属性应用到 bean 中 
     			applyPropertyValues(beanName, mbd, bw, pvs);
     		}
     	}

复制代码

在 populateBean 函数中提供了这样的处理流程:

  • InstantiationAwareBeanPostProcessor处理器的 postProcessAfterInstantiation 函数的应用, 次函数可以控制程序是否继续进行属性填充.
  • 根据注入类型 (byName/byType), 提取依赖的 bean; 并统一存入 PropertyValue 中.
  • 应用 InstantiationAwareBeanPostProcessor 处理器的 postProcessPropertyValues 方法, 对属性获取完毕填充前对属性的再次处理, 典型应用是 RequiredAnnotationBeanPostProcessor 类中对属性的验证.
  • 将所有 PropertyValues 中的属性填充至 BeanWrapper 中.

在上面的步骤中有几个地方是我们比较感兴趣的, 他们分别是依赖注入(autowireByName/autowireByType) 以及属性填充, 那么, 接下里进一步分析这几个功能的实现细节.

  1. autowireByName

    上文提到根据注入类型 (byName/byType), 提取依赖的bean吗并统一存入PropertyValues中, 那么我们首先了解下 byName 功能是如何实现的.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByName

    protected void autowireByName(
    		String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
    	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    	for (String propertyName : propertyNames) {
    		if (containsBean(propertyName)) {
    			Object bean = getBean(propertyName);
    			pvs.add(propertyName, bean);
    			registerDependentBean(propertyName, beanName);
    			if (logger.isTraceEnabled()) {
    				logger.trace("Added autowiring by name from bean name '" + beanName +
    						"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
    			}
    		}
    		else {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
    						"' by name: no matching bean found");
    			}
    		}
    	}
    }
    
    复制代码
  2. autowireByType

    autowireByType 与 autowireByName 对于我们理解与使用来说复杂程度都很相似, 但是其实现功能的复杂度却完全不一样.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByType

    protected void autowireByType(
    		String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
    	TypeConverter converter = getCustomTypeConverter();
    	if (converter == null) {
    		converter = bw;
    	}
    
    	Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    	// 寻找bw中需要依赖注入的属性
    	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    	for (String propertyName : propertyNames) {
    		try {
    			PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
    			// Don't try autowiring by type for type Object: never makes sense,
    			// even if it technically is a unsatisfied, non-simple property.
    			if (Object.class != pd.getPropertyType()) {
    				// 探测定位属性的 set 方法
    				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
    				// Do not allow eager init for type matching in case of a prioritized post-processor.
    				boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
    				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
    				// 解析指定 beanName 的属性所匹配的值, 并把解析到的属性名称存储在 autowireBeanName 中, 当属性存在多个封装的 bean 时如:
    				// @Autowired private List<A> aList; 将会找到所有匹配A类型的bean并将其注入
    				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
    				if (autowiredArgument != null) {
    					pvs.add(propertyName, autowiredArgument);
    				}
    				for (String autowiredBeanName : autowiredBeanNames) {
    					// 注册依赖
    					registerDependentBean(autowiredBeanName, beanName);
    					if (logger.isTraceEnabled()) {
    						logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
    								propertyName + "' to bean named '" + autowiredBeanName + "'");
    					}
    				}
    				autowiredBeanNames.clear();
    			}
    		}
    		catch (BeansException ex) {
    			throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
    		}
    	}
    }
    
    复制代码

    实现根据名称自动匹配的第一步就是寻找 bw 中需要依赖注入的属性, 同样对于根据类型自动匹配的实现来讲第一步也是寻找bw中需要依赖注入的属性, 然后遍历这些属性并寻找类型匹配的bean, 其中最复杂的就是寻找类型匹配的 bean. 同事 Spring 中提供了对集合的类型注入的支持. 如使用注解的方式:

    @Autowired private List<Test> tests;
    
    复制代码

    Spring 将会把所有与 Test 匹配的类型找出来并出入到 tests 属性中, 正式由于这一因素, 所以在 autowireByType 函数中, 新建了局部遍历 autowiredBeanNames, 用于存储所有依赖的 bean, 如果只是对非集合类的属性注入来说, 此属性并无用处.

    对于寻找类型匹配的逻辑实现封装在了 resolveDependency 函数中.

    DefaultListableBeanFactory#resolveDependency

    @Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
    		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
    	descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    	if (Optional.class == descriptor.getDependencyType()) {
    		return createOptionalDependency(descriptor, requestingBeanName);
    	}
    	else if (ObjectFactory.class == descriptor.getDependencyType() ||
    			ObjectProvider.class == descriptor.getDependencyType()) {
    // ObjectFactory 类注入的特殊处理
    		return new DependencyObjectProvider(descriptor, requestingBeanName);
    	}
    	else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
    // javaxInjectProviderClass 类注入的特殊处理
    		return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    	}
    	else {
    		Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
    				descriptor, requestingBeanName);
    		if (result == null) {
     // 通用逻辑处理
    			result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    		}
    		return result;
    	}
    }
    
    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    	/*
    		用于支持 Spring 中新增的注解 @Value
    	*/
    	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    	try {
    		Object shortcut = descriptor.resolveShortcut(this);
    		if (shortcut != null) {
    			return shortcut;
    		}
    
    		Class<?> type = descriptor.getDependencyType();
    		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
    		if (value != null) {
    			if (value instanceof String) {
    				String strVal = resolveEmbeddedValue((String) value);
    				BeanDefinition bd = (beanName != null && containsBean(beanName) ?
    						getMergedBeanDefinition(beanName) : null);
    				value = evaluateBeanDefinitionString(strVal, bd);
    			}
    			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
    			try {
    				return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
    			}
    			catch (UnsupportedOperationException ex) {
    				// A custom TypeConverter which does not support TypeDescriptor resolution...
    				return (descriptor.getField() != null ?
    						converter.convertIfNecessary(value, type, descriptor.getField()) :
    						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
    			}
    		}
    
    		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
    		if (multipleBeans != null) {
    			return multipleBeans;
    		}
    
    		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    		if (matchingBeans.isEmpty()) {
    			if (isRequired(descriptor)) {
    				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    			}
    			return null;
    		}
    
    		String autowiredBeanName;
    		Object instanceCandidate;
    
    		if (matchingBeans.size() > 1) {
    			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    			if (autowiredBeanName == null) {
    				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
    					return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
    				}
    				else {
    					// In case of an optional Collection/Map, silently ignore a non-unique case:
    					// possibly it was meant to be an empty collection of multiple regular beans
    					// (before 4.3 in particular when we didn't even look for collection beans).
    					return null;
    				}
    			}
    			instanceCandidate = matchingBeans.get(autowiredBeanName);
    		}
    		else {
    			// We have exactly one match.
    			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
    			autowiredBeanName = entry.getKey();
    			instanceCandidate = entry.getValue();
    		}
    
    		if (autowiredBeanNames != null) {
    			autowiredBeanNames.add(autowiredBeanName);
    		}
    		if (instanceCandidate instanceof Class) {
    			instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    		}
    		Object result = instanceCandidate;
    		if (result instanceof NullBean) {
    			if (isRequired(descriptor)) {
    				raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    			}
    			result = null;
    		}
    		if (!ClassUtils.isAssignableValue(type, result)) {
    			throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
    		}
    		return result;
    	}
    	finally {
    		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    	}
    }
    
    复制代码

    寻找类型的匹配执行顺序时, 首先尝试使用解析器进行解析, 如果解析器没有成功解析, 那么可能是使用默认的解析器没有做任何处理, 或者是使用了自定义的解析器, 但是对于集合等类型来说并不在解析范围之内, 所以再次对不同类型进行不同情况的处理, 虽说对于不同了性处理方式不一致, 但是大致的思路还是很相似的, 所以函数中只对数组类型进行了详细的注释.

  3. applyPropertyValues

    程序运行到这里, 已经完成了对所有注入属性的获取, 但是获取的属性是以Propertyvalues形式存在的, 还并没有应用到已经实例化的bean中, 这一工作是在applyPropertyValues中.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues

    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    	if (pvs == null || pvs.isEmpty()) {
    		return;
    	}
    
    	MutablePropertyValues mpvs = null;
    	List<PropertyValue> original;
    
    	if (System.getSecurityManager() != null) {
    		if (bw instanceof BeanWrapperImpl) {
    			((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    		}
    	}
    
    	if (pvs instanceof MutablePropertyValues) {
    		mpvs = (MutablePropertyValues) pvs;
        // 如果mpvs中的值已经被转换为对应的类型那么可以直接设置到beanwrapper中
    		if (mpvs.isConverted()) {
    			// Shortcut: use the pre-converted values as-is.
    			try {
    				bw.setPropertyValues(mpvs);
    				return;
    			}
    			catch (BeansException ex) {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    			}
    		}
    		original = mpvs.getPropertyValueList();
    	}
    	else {
        // 如果pvs并不是使用MutablePropertyValues封装的类型, 那么直接使用原始的属性获取方法
    		original = Arrays.asList(pvs.getPropertyValues());
    	}
    
    	TypeConverter converter = getCustomTypeConverter();
    	if (converter == null) {
    		converter = bw;
    	}
      // 获取对应的解析器
    	BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
    
    	// Create a deep copy, resolving any references for values.
    	List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
    	boolean resolveNecessary = false;
      // 遍历属性, 将属性转换为对应类的对应属性的类型
    	for (PropertyValue pv : original) {
    		if (pv.isConverted()) {
    			deepCopy.add(pv);
    		}
    		else {
    			String propertyName = pv.getName();
    			Object originalValue = pv.getValue();
    			Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    			Object convertedValue = resolvedValue;
    			boolean convertible = bw.isWritableProperty(propertyName) &&
    					!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
    			if (convertible) {
    				convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
    			}
    			// Possibly store converted value in merged bean definition,
    			// in order to avoid re-conversion for every created bean instance.
    			if (resolvedValue == originalValue) {
    				if (convertible) {
    					pv.setConvertedValue(convertedValue);
    				}
    				deepCopy.add(pv);
    			}
    			else if (convertible && originalValue instanceof TypedStringValue &&
    					!((TypedStringValue) originalValue).isDynamic() &&
    					!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
    				pv.setConvertedValue(convertedValue);
    				deepCopy.add(pv);
    			}
    			else {
    				resolveNecessary = true;
    				deepCopy.add(new PropertyValue(pv, convertedValue));
    			}
    		}
    	}
    	if (mpvs != null && !resolveNecessary) {
    		mpvs.setConverted();
    	}
    
    	// Set our (possibly massaged) deep copy.
    	try {
    		bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    	}
    	catch (BeansException ex) {
    		throw new BeanCreationException(
    				mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    	}
    }
    
    复制代码

5.7.4 初始化bean

大家应该记得在 bean 配置时 bean 中有一个 init-method 的属性, 这个属性的作用是在 bean 实例化前调用 init-method 指定的方法来根据用户业务进行相应的实例化. 我们现在就已经进入这个方法了, 首先看一下这个方法的执行位置, Spring 中程序已经执行过 bean 的实例化, 并且进行了属性的填充, 而就在这时将会调用用户设定的初始化方法.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			@Override
			public Object run() {
				invokeAwareMethods(beanName, bean);
				return null;
			}
		}, getAccessControlContext());
	}
	else 
    // 对特殊的 bean 处理: Aware, BeanClassLoaderAware, BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
    // 应用后处理器
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
    // 激活用户自定义的 init 方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				(mbd != null ? mbd.getResourceDescription() : null),
				beanName, "Invocation of init method failed", ex);
	}

	if (mbd == null || !mbd.isSynthetic()) {
    // 后处理器应用
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}

复制代码

虽然说此函数的主要目的是进行客户设定的初始化方法的调用, 但是除此之外还有些其他必要的工作.

  1. 激活 Aware 方法

    在分析其原理之前, 我们先了解一下 Aware 的使用. Spring 中提供了一些 Aware 相关接口, 比如 BeanFactoryAware, ApplicationContextAware, ResourceLoaderAware, ServletContextAware等, 实现这些Aware 接口的 bean 在被初始化之后, 可以取得一些相应的资源, 例如实现 BeanFactoryAware 的 bean 在初始后, Spring 容器将会注入 BeanFactory 的实例, 而实现 ApplicationContextAware 的 bean, 在 bean 被初始后, 将会被注入 ApplicationContext 的实例等, 我们首先通过示例方法来了解一下 Aware 的应用.

    (1) 定义普通 bean

    public class Hello {
      public void say() {
        System.out.println("hello");
      }
    }
    
    复制代码

    (2) 定义 BeanFactoryAware 类型的 bean

    public class Test implements BeanFactoryAware {
      private BeanFactory beanFactory;
      
      // 声明 bean 的时候 Spring 会自动注入 BeanFactory
      @Override
      public void setBeanFactory(BeanFactory beanFactory) throws BeanException {
        this.beanFactory = beanFactory;
      }
      
      public void testAware() {
        // 通过 hello 这个 bean id 从 beanFactory 获取实例
        Hello hello = (Hello) beanFactory.getBean("hello");
        hello.say();
      }
      
    }
    
    复制代码

    (3) 使用main方法测试

    public static void main(String[] s) {
      ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
      Test test = (Test) ctx.getBean("test");
      test.testAware();
    }
    
    复制代码

    裕兴测试类, 控制台输出:

    hello
    
    复制代码

    按照上面的方法我们可以获取到Spring 中BeanFactory, 并且可以根据 BeanFactory 获取所有 bean, 以及进行相关设置. 当然还有其他 Aware 的使用方法都大同小异, 看一下 Spring 的实现方式, 便会使用了.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

    private void invokeAwareMethods(final String beanName, final Object bean) {
    	if (bean instanceof Aware) {
    		if (bean instanceof BeanNameAware) {
    			((BeanNameAware) bean).setBeanName(beanName);
    		}
    		if (bean instanceof BeanClassLoaderAware) {
    			((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    		}
    		if (bean instanceof BeanFactoryAware) {
    			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    		}
    	}
    }
    
    复制代码
  2. 处理器的应用

    BeanPostProcessor 相信大家都不陌生, 这是 Spring 中开放式架构中一个必不可少的亮点, 给用户充足的权限去更改或者扩展 Spring, 而除了 BeanPostProcessor 外还有很多其他的 PostProcessor, 当然啊部分都是以此为基础, 继承自BeanPostProcessor. BeanPostProcessor的使用位置就是这里, 在调用客户自定义初始化方法前以及调用自定义初始化方法后分别会调用 BeanPostProcessor 的 postProcessBeforeInitiallization 和 postProcessAfterInitialization 方法, 使用户可以根据自己的业务需求进行响应的处理.

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessBeforeInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    
    复制代码

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessAfterInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    
    复制代码
  3. 激活自定义的init方法

    客户定制的初始化方法除了我们熟知的使用配置init-method外, 还有使自定义的bean实现 InitializingBean 接口, 并在 afterPropertiesSet 中实现自己的初始化业务逻辑.

    init-method 与 afterPropertiesSet 都是在初始化 bean 时执行, 执行顺序是 afterPropertiesSet 先执行, 而 init-method 后执行.

    在 invokeInitMethods 方法中就实现了这两个步骤的初始化方法调用.

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
    	// 首先会检查是否是 InitializingBean , 如果是的话需要调用 afterPropertiesSet 方法
    	boolean isInitializingBean = (bean instanceof InitializingBean);
    	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    		}
    		if (System.getSecurityManager() != null) {
    			try {
    				AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
    					@Override
    					public Object run() throws Exception {
    						((InitializingBean) bean).afterPropertiesSet();
    						return null;
    					}
    				}, getAccessControlContext());
    			}
    			catch (PrivilegedActionException pae) {
    				throw pae.getException();
    			}
    		}
    		else {
          // 属性初始化后的处理
    			((InitializingBean) bean).afterPropertiesSet();
    		}
    	}
    
    	if (mbd != null) {
    		String initMethodName = mbd.getInitMethodName();
    		if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    				!mbd.isExternallyManagedInitMethod(initMethodName)) {
          // 调用自定义初始化方法
    			invokeCustomInitMethod(beanName, bean, mbd);
    		}
    	}
    }
    
    复制代码

5.7.5 注册DisposableBean

Spring 中不但提供了对于初始化方法的扩展入口, 同样也提供了销毁方法的扩展入口, 对于销毁方法的扩展, 除了我们熟知的配置属性 destroy-method 方法外, 用户还可以注册后处理器 DestructionAwareBeanPostProcessor 来统一处理 bean 的销毁方法, 代码如下:

org.springframework.beans.factory.support.AbstractBeanFactory#registerDisposableBeanIfNecessary

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
		if (mbd.isSingleton()) {
			// 单例模式下注册需要销毁的 bean , 此方法中会处理实现 DisposableBean 的 bean, 并且对所有的 bean 使用 DestructionAwareBeanPostProcessor 处理 DisposableBean DestructionAwareBeanPostProcessors
			registerDisposableBean(beanName,
					new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
		else {
			// 自定义 scope 的处理
			Scope scope = this.scopes.get(mbd.getScope());
			if (scope == null) {
				throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
			}
			scope.registerDestructionCallback(beanName,
					new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
		}
	}
}

复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms of the Intelligent Web

Algorithms of the Intelligent Web

Haralambos Marmanis、Dmitry Babenko / Manning Publications / 2009-7-8 / GBP 28.99

Web 2.0 applications provide a rich user experience, but the parts you can't see are just as important-and impressive. They use powerful techniques to process information intelligently and offer featu......一起来看看 《Algorithms of the Intelligent Web》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具