Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路

写在前面

上面四篇文章讲了Spring是如何将配置文件一步一步转化为BeanDefinition的整个流程,下面就到了正式创建Bean对象实例的环节了,我们一起继续学习吧。

2.初始化Bean对象实例

Resource resource = new ClassPathResource("beanFactory.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Student student = beanFactory.getBean(Student.class);

仍然使用我们最开的一串代码来讲解,前四章我们说了那么多其实只是创建了BeanFactory这个容器,并将BeanDefinition对象解析完毕,而真正的对象创建则是在BeanFactory.getBean()中执行的。

2.1 起源,探寻Bean的新生之路

一切起源于BeanFactory.getBean(),而对getBean()的实现是在AbstractBeanFactory这个类中实现的,所以我们着眼此类进行源码的阅读。如下为AbstractBeanFactory的继承实现图

getBean方法源码

getBean()方法调用了本类中自定义的doGetBean方法,接下来进入doGetBean()方法观察。

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//1、解析beanName,找出bean真正的名称
		final String beanName = transformedBeanName(name);
		Object bean;

		//2.尝试从单例缓存池中直接获取对象
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
			//3.该容器缓存中没有,开始尝试加载父容器,检查父容器中是否存在该Bean对象
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
			//4.父容器中仍然不存在,获取解析好的BeanDefinition,开始准备自己创建Bean
			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//获取bean的根路径信息
				checkMergedBeanDefinition(mbd, beanName, args);
				//重要一步,检查依赖关系,提前创建依赖的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);
						getBean(dep);
					}
				}
				//5.检查BeanDefinition的scope属性,并执行不同的创建方法,总体大同小异,着重关注单例的创建方法即可。
				if (mbd.isSingleton()) {
					//6、极为重要的一点,通过getSingleton(String beanName,ObjectFactory objectFactory)创建对象,并且实例化getObject()方法
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								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, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								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;
			}
		}
		if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

上面的代码很长,乍一看真的会让初学者头皮发麻,但是没关系,我们将它拆解开来一步一步分析。

  1. transformedBeanName(String):提取对应Bean的名称。定义在SimpleAliasRegistry中,用于获取bean的真实名称。
  2. DefaultSingletonBeanRegistry.getSingleton(Stirng,Boolean):尝试从缓存中直接获取bean或者通过ObjectFactory中获取。关于此方法的详解,请点击。
  3. getObjectForBeanInstance():根据Bean取出我们真正需要的对象(判断指定的bean是否是一个FactoryBean,如果是FactoryBean会判断需求的是本身还是factory的创建对象。)
  4. isPrototypeCurrentlyInCreation(beanName):判断是否进入了循环依赖的无限循环
  5. registerDependentBean(dep, beanName):此段代码主要是找出当前Bean的所有依赖对象,并且循环对这些依赖进行注册和创建。
  6. getSingleton(String,ObjectFactory):针对不同的scope进行各自的初始化操作。
  7. 做最后的类型转换(还不太懂)

至此,一个bean的完整创建流程就走完了。具体的细节,我们接下来一个一个慢慢的看。


2.2 明辨,找出我们真正的目标

首先,我们进入第一段代码

在transformedBeanName(beanName)中,传入的参数并非真正的beanName,这里的参数可能是别名,也可能是factoryBean的名称,所以要进行一系列的解析,主要的解析分为两步:

  1. 尝试解析是否是FactoryBean名称,(关于FactoryBean如果不理解,可以访问:Spring之FactoryBean 代码如下:
	//解析是否是FactoryBean:BeanFactoryUtils.transformedBeanName(String name)
	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		String beanName = name;
		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		}
		return beanName;
	}
	代码很简单,就是判断beanName是否是以“&”开头,然后进行截取。
  1. 尝试判断该名称是否是某个bean的别名。
	//判断别名:SimpleAliasRegistry.canonicalName(String name)
	public String canonicalName(String name) {
		String canonicalName = name;
		String resolvedName;
		do {
      //从别名集合中循环查找,直到最底层真正的bean名称
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}
依然很简单,尝试从实现定义好的别名集合中进行查询,寻找真正的bean。

2.3 尝试从缓存中直接获取对象

接下来是doGetBean中的第三个方法,getSingleton(String beanName, boolean allowEarlyReference)

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//1.尝试从单例缓存中直接获取对象
	Object singletonObject = this.singletonObjects.get(beanName);
	//2.如果单例缓存中无法获取对象,且该对象在正在创建对象标记池里。
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			//3.从提前创建对象池中获取该对象
			singletonObject = this.earlySingletonObjects.get(beanName);
			//4.对象仍然为空且允许循环依赖
			if (singletonObject == null && allowEarlyReference) {
				//5.尝试从ObjectFactory池中获取对象的ObjectFactory,并创建该对象。
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

public boolean isSingletonCurrentlyInCreation(String beanName) {
	return this.singletonsCurrentlyInCreation.contains(beanName);
}

此方法代码其实不难理解,主要的难点是几个概念上的问题。首先观察该方法中用到的该类的几个参数。

  1. 单例对象缓存池
    /** Cache of singleton objects: bean name --> bean instance */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
    
    如注解,这是Spring的单例对象池,所有的单例对象创建完毕后都会以beanName ->singletonObject 的形式放入该Map集合中
  2. 对象预创建标记池
    /** Names of beans that are currently in creation */
    private final Set<String> singletonsCurrentlyInCreation =
    		Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
    
    这是Spring为了解决循环依赖的一个标记集合,具体概念留在后面介绍
  3. 预创建单例对象缓存池
    /** Cache of early singleton objects: bean name --> bean instance */
    private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    
    此集合是保存预创建单例对象的集合
  4. 预创建单例对象缓存池
    /** Cache of singleton factories: bean name --> ObjectFactory */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
    
    此集合是保存ObjectFactory的集合,至于何时、何种情况Spring会创建ObjectFactory。且ObjectFactory、BeanFacotry、FactoryBean他们的关系,也在下面会做说明。

小tip:ObjectFactory、BeanFactory、FactoryBean之间的关系和联系

  • BeanFactory:这是我们大家非常熟悉的接口,Spirng管理Bean容器最原始接口,我们此次研究的入口getBean()就是在此接口中定义。
  • FactoryBean:在上文2.2中我们已经讨论了FactoryBean的情况,作为一个Bean的工厂对象,它也可以作为一个bean对象直接获取,关于BeanFactory和FactoryBean的详细信息,可查看该文章:BeanFactory和FactoryBean
  • ObjectFactory:与FactoryBean很相似的是ObjectFactory也是用于创建一个对象的,且它存在的意义主要用于解决循环依赖。例如A、B两个对象,A中有B属性,B中有A属性。那么在创建A时发现需要注入B,这时创建B,在创建B时发现又需要注入A,这就形成了循环依赖。而Spring正是利用ObjectFactory解决了这个问题,其原理就是在创建A时就将一个A的ObjectFactory对象放入了缓存中,那么在B注入A时就用这个ObjectFactory创建的对象注入B中,这样就解决了循环依赖的问题。具体的代码在下面会详细介绍。

2.4根据Bean实例,获取真正需要的对象(FactoryBean的特殊处理场景)

getObjectForBeanInstance()是一个非常重要的方法,Spring在获取了每个Bean的对象之后,都要调用该方法完成最后的步骤以取得我们真正想要的Bean。说到很多人肯定会疑惑,什么是“真正需要”,点进该方法,我们就知道了。

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

	if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
	}

	//判断实例不是FactoryBean类型或该实例名称以获取FactoryBean开头 ,满足任何一个条件直接返回实例
	//即满足两个条件无非有两个条件1.该对象不是FactoryBean,判断短路直接返回。2.该对象是FactoryBean,且用户想直接获取FactoryBean
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}

	Object object = null;
	if (mbd == null) {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		//通过上述,至此可以完全确定该对象是Factory对象,下方就是通过对象的factory-method创建对象的过程。
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		boolean synthetic = (mbd != null && mbd.isSynthetic());
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}

上述重要就是一个短路判断,如果该对象不是一个FactoryBean或者用户试图直接获取FactoryBean对象,则该对象就已经是我们想要的对象,直接返回即可,否则的话就意味着我们需要通过FactoryBean内部定义好的factory-method来创建我们需要的Bean对象。而我们追入getObjectFromFactoryBean()中,查看如下代码:

//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);
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (object != null && shouldPostProcess) {
							try {
                //执行后处理器
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
						}
						this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
					}
				}
				return (object != NULL_OBJECT ? object : null);
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (object != null && shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

而遗憾的是我们还是没有看到真正创建对象的方法,但通过前面的阅读,我们已经可以发现Spring在一个方法的真正核心处理部分处,都会以doXXXX开头,而其余都是对这个核心处理的一层层包装与协助。

2.4.1代码如莲花开放般的优美:处理器BeanPostProcess

在观察核心代码之前,我们先观察后面一个重要的方法。postProcessObjectFromFactoryBean(),在spring的整个架构中给予了用户各种拓展和自定义的权利,这也是Spring被广泛称赞:代码优美的原因之一。而这里的执行后处理器操作就是很重要的一环,进入该方法的子类AbstractAutowireCapableBeanFactory观察Spirng是如何让代码变得如此优美的。

	//AbstractAutowireCapableBeanFactory.java
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
			return applyBeanPostProcessorsAfterInitialization(object, beanName);
	}

	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;
	}
//BeanPostProcessor.java
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

观察代码,可以知道Spring循环了Bean所注册的所有BeanPostProcess,并在这里依次调用了其postProcessAfterInitialization()方法,而该方法的实现交由用户来自己实现。于是乎,通过解析我们就能知道:在Spring中:如果想让一个Bean在初始化完成后做一些特殊处理,实现BeanPost.postProcessAfterInitialization()即可。最后有一个小提醒:我们一定要清晰的认识到,此时我们是在修饰一个FactoryBean创建的Bean对象,而并非正常流程创建的Bean对象哦,例如我们一直讨论的这个FactoryBean,它本身作为一个Bean对象是在什么时候执行了PostPorcess方法了呢?后续我们拭目以待吧

2.4.2柳暗花明,终于获取最终需要的对象

了解完处理器之后,让我们点入doGetObjectFromFactoryBean(),发现里面的代码就非常简单明了。

//FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(...)
	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(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
								//调用Factory的getObject方法
								return factory.getObject();
							}
						}, acc);
				}catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}else {
			//调用Factory的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);
		}
		if (object == null && isSingletonCurrentlyInCreation(beanName)){
			throw new BeanCurrentlyInCreationException(
					beanName, "FactoryBean which is currently in creation returned null from getObject");
		}
		return object;
	}

一层一层终于我们到了最里边,在这里我们发现最终对象正是由当初获取的FactoryBean对象的getObject()方法完成。如果读到这里已经有些绕不过来,想不起自己从何处而来的话,往上翻一翻,看清楚自己一路走来之路哦。下面我们就重新回到起源之路上,继续往下探索。但由于真正的Bean的创建流程很长,所以这篇文章先写到这里,下面单开一篇文章来写Bean对象的实例化。

posted @ 2019-04-05 22:28  ZzlevolFlash  阅读(171)  评论(0编辑  收藏  举报