Spring 5.0源码解读:Bean容器DefaultListableBeanFactory

引言

在Spring中,BeanFactory是IoC容器的核心接口,它负责管理所有的Bean,解决各种Bean与Bean之间的依赖关系。BeanFactory接口有一个经典的实现类就是DefaultListableBeanFactory
在这里插入图片描述

测试代码

@Test
public void beanFactoryTest() {
	Resource xmlSrc = new ClassPathResource("test/context.xml");
	BeanFactory bf = new DefaultListableBeanFactory();
	BeanDefinitionReader bdr = new XmlBeanDefinitionReader((BeanDefinitionRegistry) bf);
	bdr.loadBeanDefinitions(xmlSrc);
	TestBean tb = bf.getBean("testBean", TestBean.class);
	System.out.println(tb);
}

在上篇文章中我们已经学习到了XmlBeanDefinitionReader是如何加载Bean XML配置文件并写入到BeanDefinitionRegistry,那么本篇文章我们来分析DefaultListableBeanFactory是如何注册Bean、加载Bean的。


BeanDefinition的注册

XmlBeanDefinitionReader解析XML文档的过程中需要将解析后的产物BeanDefinition写入到BeanDefinitionRegistry,那么DefaultListableBeanFactory是如何实现这个功能的呢?答案就在registerBeanDefinition这个方法中:

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException {
	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) { 
		try {
			//进行Bean的验证操作,判断其属性是否合法
			((AbstractBeanDefinition) beanDefinition).validate();
		} catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
		}
	}
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {	//如果有相同Bean
		if (!isAllowBeanDefinitionOverriding()) {  //如果不允许被覆盖,那么抛出异常
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		} else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		} else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		} else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		//将bean id和BeanDefinition关系存入Map中
		this.beanDefinitionMap.put(beanName, beanDefinition);
	} else {
		if (hasBeanCreationStarted()) { //如果BeanFactory已经开始加载Bean
			synchronized (this.beanDefinitionMap) { //给Map加锁
				this.beanDefinitionMap.put(beanName, beanDefinition); //将bean id和BeanDefinition关系存入Map中
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				//将这个Bean的ID、所有的别名添加到List
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		} else { //如果BeanFactory未处于初始化/运行状态,那么就无需保证其线程安全性
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
}

BeanFactory加载Bean的过程

当所有的BeanDefinition成功注册到DefaultListableBeanFactory后,接下来便可以调用它的相关方法获取Bean了。
当我们调用BeanFactorygetBean等方法时,BeanFactory就会加载用户所需要的Bean。
首先说明下,DefaultListableBeanFactory是一个线程安全的类,可以支持多个线程同时操作DefaultListableBeanFactory,所以其内部代码采用了很多多线程设计的思想。

我们从getBean(String name, Class<T> requiredType)方法开始解析:

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	return doGetBean(name, requiredType, null, false);
}

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	//...
}

doGetBean方法代码量比较大,可以看出Bean的加载还是一个比较复杂的一个过程,我们来分步解析这个方法:

1、转换name为beanName
final String beanName = transformedBeanName(name);

首先doGetBean会通过调用transformedBeanName方法处理传入的name参数。

protected String transformedBeanName(String name) {
	return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

public static String transformedBeanName(String name) {
	Assert.notNull(name, "'name' must not be null");
	if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
		return name;
	}
	//将name属性的前面“&”字符裁剪掉
	return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
		do {
			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		} while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
	});
}

public String canonicalName(String name) {
	String canonicalName = name;
	String resolvedName;
	do { //循环查找Bean的唯一ID(beanName)
		resolvedName = this.aliasMap.get(canonicalName);
		if (resolvedName != null) {
			canonicalName = resolvedName;
		}
	}
	while (resolvedName != null);
	return canonicalName;
}

回顾一下Spring的基础知识,如果一个Bean属于FactoryBean类型,那么在传入这个Bean的name时,获取的是FactoryBean调用getObject方法的对象,如果需要获取FactoryBean本身,那么需要在name前加入字符’&’。

getBean方法除了可以传入Bean的ID来获取Bean,还可以传入Bean的别名来获取。在Spring中,Bean可以取别名,别名同样可以再取一个别名,这种关系通过成员变量aliasMap保存。所以可以看到上述canonicalName方法通过一个循环来层层递进,找到这个Bean的唯一标识符ID。

2、尝试从当前BeanFactory的缓存中找到单例
Object bean;
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 = getObjectForBeanInstance(sharedInstance, name, beanName, null); //返回对应的实例
}

首先会调用getSingleton尝试从缓存中寻找是否有对应的实例:

@Override @Nullable
public Object getSingleton(String beanName) {
	return getSingleton(beanName, true);
}

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//从缓存中找到实例
	Object singletonObject = this.singletonObjects.get(beanName);
	//如果没有在缓存中找到实例并且当前实例处于正在创建的状态
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

这里为什么会出现没有在缓存中找到实例并且该实例处于正在创建的状态呢?因为这是Spring解决Singleton Bean的循环依赖的机制产生的,Spring解决循环依赖的方式是通过提前曝光的方式(具体是将可以创建这个单例的ObjectFactory实例添加到singletonFactories),当BeanFactory检测到循环依赖后,就会将依赖的对象提前创建好,并添加到earlySingletonObjects中。需要注意的是,singletonObjects缓存只负责存放已经完全生成好的单例Bean实例。

如果getSingleton成功获取到了单例Bean对象,那么接下来就会调用getObjectForBeanInstance对这个对象进行进一步的处理:

protected Object getObjectForBeanInstance(Object beanInstance, String name, 
		String beanName, @Nullable RootBeanDefinition mbd) {
	//如果name以'&'开头
	if (BeanFactoryUtils.isFactoryDereference(name)) {
		if (beanInstance instanceof NullBean) {
			return beanInstance;
		}
		if (!(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}
	}
	//如果实例不属于FactoryBean类型或者name以'&'开头,那么直接返回实例
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}
	//如果是属于FactoryBean类型的Bean
	Object object = null;
	if (mbd == null) { //尝试从缓存中获取FactoryBean生产的实例
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) { //如果没有从缓存中拿到FactoryBean实例
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		//是否指定了FactoryBean的ID(beanName),如果指定了就获取它的RootBeanDefinition
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		//检查是否是用户定义的而不是应用程序定义的
		boolean synthetic = (mbd != null && mbd.isSynthetic());
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}

在上述方法中,如果检测到name以’&'开头并且这个Bean不属于FactoryBean,那么就会抛出异常,否则,直接返回这个Bean的实例。
接下来,便是对FactoryBean的处理了。首先会尝试获取这个Bean的RootBeanDefinition对象,并判断它是否是“合成”的(合成的Bean即不是由应用程序本身定义的Bean,例如通过AOP代理后生成的Bean)。然后会尝试调用getCachedObjectForFactoryBean从缓存中拿到FactoryBean生产的实例:

@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
	return this.factoryBeanObjectCache.get(beanName);
}

如果没有成功从缓存中拿到实例,那么接下来就会调用getObjectFromFactoryBean方法获取实例:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	//如果生产的实例的是单例并且单例缓存中包含这个FactoryBean的实例
	if (factory.isSingleton() && containsSingleton(beanName)) {
		synchronized (getSingletonMutex()) {
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
				//该方法会调用FactoryBean的getObject方法生产实例
				object = doGetObjectFromFactoryBean(factory, beanName);
				//确保只有一个实例
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				} else {
					if (shouldPostProcess) {
						if (isSingletonCurrentlyInCreation(beanName)) { //解决循环依赖
							return object;
						}
						//将BeanName放入singletonsCurrentlyInCreation集合,表示正在处理这个Bean
						beforeSingletonCreation(beanName);
						try {
							//获取当前BeanFactory持有的BeanPostProcessor进行处理
							object = postProcessObjectFromFactoryBean(object, beanName);
						} catch (Throwable ex) {
							throw new BeanCreationException(beanName,
									"Post-processing of FactoryBean's singleton object failed", ex);
						} finally {
							//将BeanName从singletonsCurrentlyInCreation集合移除,表示创建完成
							afterSingletonCreation(beanName);
						}
					}
					将这个生产的实例放入FactoryBean单例缓存
					if (containsSingleton(beanName)) { 
						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
			}
			return object;
		}
	} else {
		//同样是调用FactoryBean的getObject方法生产实例
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (shouldPostProcess) { //如果需要调用BeanPostProcessor进行处理
			try {
				//获取当前BeanFactory持有的BeanPostProcessor进行处理
				object = postProcessObjectFromFactoryBean(object, beanName);
			} catch (Throwable ex) {
				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
			}
		}
		return object;
	}
}

执行步骤为:
1、如果FactoryBean生产的Bean是单例Bean(即getObject方法始终返回同一个对象),并且单例缓存中持有这个FactoryBean对象,那么首先尝试从FactoryBean单例缓存(负责存储FactoryBean生产的单例Bean)中获取实例。如果成功获取则直接返回,如果获取不成功,则直接调用doGetObjectFromFactoryBean方法通过FactoryBeangetObject方法生产实例。生产实例后,会再次检查FactoryBean单例缓存有没有这个Bean(这里主要是为了防止FactoryBean内部的getObject方法调用了当前BeanFactorygetBean方法产生了循环依赖问题后造成的循环依赖问题)。如果检测到已经产生了这个Bean,那么直接返回。否则将根据参数shouldPostProcess决定是否进行Bean的后处理。
后处理会遍历该容器持有的所有BeanPostProcessor并通过它们依次对Bean进行处理(例如处理@Autowired注解修饰的变量)

2、如果不满足上述条件,则直接调用doGetObjectFromFactoryBean生产Bean然后通过所有的BeanPostProcessor进行处理。

3、如果缓存中没有对应的实例。那么会检查是否发生了循环依赖:
if (isPrototypeCurrentlyInCreation(beanName)) { //如果发生了循环依赖
	throw new BeanCurrentlyInCreationException(beanName);
}

protected boolean isPrototypeCurrentlyInCreation(String beanName) {
	Object curVal = this.prototypesCurrentlyInCreation.get();
	return (curVal != null && (curVal.equals(beanName) || 
		   (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}

Spring会主动解决Singleton作用域的循环依赖问题。对于Prototype作用域的Bean所产生的循环依赖,Spring会直接抛出BeanCurrentlyInCreationException异常。

上述方法只是检测非Singleton作用域的Bean有没有发生循环依赖。那么Spring是如何检查到非Singleton作用域的Bean发生了循环依赖的呢?
我们假设Bean A和B互相依赖。Spring会在构造非Singleton作用域的Bean的时候,在当前线程构造一个缓存(通过ThreadLocal),并将正在构造的对象A加入这个缓存。在后续方法中,发现这个对象A依赖于对象B,于是开始了对象B的加载,在加载对象B的过程中,同样将对象B丢入这个缓存,接着对象B发现又依赖于对象A,此时会尝试实例化A,这个时候就发现缓存中已经有A的实例了,也就是isPrototypeCurrentlyInCreation返回true。

4、首先从父BeanFactory中查找是否有用户需要的Bean:
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
	String nameToLookup = originalBeanName(name);
	if (parentBeanFactory instanceof AbstractBeanFactory) {
		return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
			nameToLookup, requiredType, args, typeCheckOnly);
	} else if (args != null) {
		return (T) parentBeanFactory.getBean(nameToLookup, args);
	} else if (requiredType != null) {
		return parentBeanFactory.getBean(nameToLookup, requiredType);
	} else {
		return (T) parentBeanFactory.getBean(nameToLookup);
	}
}

如果满足当前BeanFactory持有父BeanFactory并且当前BeanFactory没有这个Bean,那么就会调用它的getBean方法查找Bean并返回。

5、如果不是仅仅对这个Bean进行类型检查而是要创建这个Bean的实例,那么记录下这个Bean的ID(beanName)。
if (!typeCheckOnly) {
	markBeanAsCreated(beanName);
}
protected void markBeanAsCreated(String beanName) {
	//检查正在创建的Bean清单中有没有这个Bean
	if (!this.alreadyCreated.contains(beanName)) {
		synchronized (this.mergedBeanDefinitions) {
			//类似于单例模式的双重检查
			if (!this.alreadyCreated.contains(beanName)) { 
				clearMergedBeanDefinition(beanName);
				this.alreadyCreated.add(beanName);
			}
		}
	}
}

上述方法会检查正在创建的Bean清单中有没有这个Bean,如果存在则跳出方法。如果不存在,那么clearMergedBeanDefinition将这个Bean的RootBeanDefinition从缓存中移除,以防止Bean在创建过程中RootBeanDefinition一些元数据发生变化。

6、将GenericBeanDefinition(只负责存储XML数据)转换为RootBeanDefinition
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
	RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
	if (mbd != null) {
		return mbd;
	}
	return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

首先会从缓存mergedBeanDefinitions中查找是否已经有处理好的RootBeanDefinition。如果没有,则进行GenericBeanDefinition的合并处理:

protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
		throws BeanDefinitionStoreException {
	return getMergedBeanDefinition(beanName, bd, null);
}

protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {
	synchronized (this.mergedBeanDefinitions) {
		RootBeanDefinition mbd = null;
		if (containingBd == null) {
			//再次从缓存中获取RootBeanDefinition
			mbd = this.mergedBeanDefinitions.get(beanName);
		}
		if (mbd == null) {
			if (bd.getParentName() == null) { //如果没有父Bean
				if (bd instanceof RootBeanDefinition) {
					mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
				} else { //构造一个RootBeanDefinition,并将GenericBeanDefinition内容复制进去
					mbd = new RootBeanDefinition(bd);
				}
			} else {
				BeanDefinition pbd;
				try {
					//获取父Bean的名称
					String parentBeanName = transformedBeanName(bd.getParentName());
					if (!beanName.equals(parentBeanName)) { //如果有父Bean名称和当前Bean名称不同
						//获取父Bean的RootBeanDefinition(这里会递归合并父Bean属性)
						pbd = getMergedBeanDefinition(parentBeanName);
					} else { //如果相同,那么尝试从父BeanFactory查找
						BeanFactory parent = getParentBeanFactory();
						if (parent instanceof ConfigurableBeanFactory) {
							pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
						} else { //如果没有父BeanFactory或者不属于ConfigurableBeanFactory,抛出异常
							throw new NoSuchBeanDefinitionException(parentBeanName,
									"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
									"': cannot be resolved without an AbstractBeanFactory parent");
						}
					}
				} catch (NoSuchBeanDefinitionException ex) {
					throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
							"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
				}
				//构造父Bean的RootBeanDefinition对象
				mbd = new RootBeanDefinition(pbd);
				//将父Bean属性与当前Bean合并
				mbd.overrideFrom(bd);
			}

			// 如果没有设置scope属性,那么默认设置为单例
			if (!StringUtils.hasLength(mbd.getScope())) {
				mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
			}
			if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
				mbd.setScope(containingBd.getScope());
			}
			//将RootBeanDefinition放入缓存
			if (containingBd == null && isCacheBeanMetadata()) {
				this.mergedBeanDefinitions.put(beanName, mbd);
			}
		}
		return mbd;
	}
}

如果GenericBeanDefinition没有指定父Bean,那么只需要将GenericBeanDefinition中的信息拷贝到一个新的RootBeanDefinition对象中并返回。如果指定了父Bean,那么会首先递归合并父Bean的GenericBeanDefinition,然后这个Bean才会和父Bean的RootBeanDefinition合并为一个RootBeanDefinition。合并完成后,将RootBeanDefinition放入mergedBeanDefinitions缓存。

7、抽象Bean的检测:
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
		throws BeanDefinitionStoreException {
	if (mbd.isAbstract()) {
		throw new BeanIsAbstractException(beanName);
	}
}

这里会检测是不是抽象Bean,如果是抽象Bean则抛出异常。

8、初始化依赖的Bean(depends-on指定的Bean)
String[] dependsOn = mbd.getDependsOn();	//获取这个Bean的依赖Bean
if (dependsOn != null) {
	for (String dep : dependsOn) {	//初始化这个Bean的依赖Bean
		if (isDependent(beanName, dep)) { //如果依赖的Bean也依赖于这个Bean,那么抛出异常
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
		}
		registerDependentBean(dep, beanName); //缓存这个Bean所依赖的所有Bean的名称
		try {
			getBean(dep);//递归获取这个依赖Bean
		} catch (NoSuchBeanDefinitionException ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
		}
	}
}

这段代码通过调用RootBeanDefinitiongetDependsOn方法获取所有依赖的Bean,并遍历这些Bean来进行初始化操作。

9、对Bean的作用域进行处理

(1)如果是Singleton作用域

sharedInstance = getSingleton(beanName, () -> {
	try {
		return createBean(beanName, mbd, args);
	} catch (BeansException ex) {
		destroySingleton(beanName);
		throw ex;
	}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

首先调用getSingleton方法通过传入的ObjectFactory构造Bean:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	synchronized (this.singletonObjects) { //加锁,防止有其他线程构造实例
		//检查缓存中Bean有没有被创建,确保这个Bean的仅有一个实例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			//检查是否在Bean的destory-method中尝试调用getBean方法
			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!)");
			}
			//将这个beanName添加到一个Set集合中,表示这个单例正在构造
			beforeSingletonCreation(beanName); 
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
				//尝试构造单例,如果在此期间有其它线程抢先构造了Bean那么抛出IllegalStateException
				singletonObject = singletonFactory.getObject();
				newSingleton = true;
			} catch (IllegalStateException ex) {
				//如果有其它线程构造了这个Bean的对象,那么直接获取这个对象
				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); //将这个beanName从Set集合中移除,表示构造完成
			}
			if (newSingleton) { //将这个单例Bean添加到缓存中
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}

简单分析一下getSingleton方法的执行步骤:
1、首先对单例缓存加锁,然后判断缓存中有没有构造好的单例对象,确保只有一个Bean被构造。如果从缓存中找到了这个Bean的对象,则说明有另外一个线程抢先实例化了这个Bean,那么退出这个方法。
2、将Bean的名称加入到一个全局Set集合中,表示这个单例正处于被构造的阶段。
3、调用传入的ObjectFactorygetObject方法构造对象,getObject方法会调用BeanFactorycreateBean方法生成对象。createBean方法的代码比较复杂,所以我们稍作讨论。
4、如果发现此时有其他线程抢先构造了对象,那么则采用这个对象作为返回值。
5、将这个实例从Set集合中移除,表示构造完成。
6、将这个构造好的实例添加到缓存singletonObjects中。

(2)如果是prototype作用域

else if (mbd.isPrototype()) {	//如果不是单例
	Object prototypeInstance = null;
	try {
		beforePrototypeCreation(beanName);
		prototypeInstance = createBean(beanName, mbd, args);
	} finally {
		afterPrototypeCreation(beanName);
	}
	//检查这个Bean是不是FactoryBean,并进行相应处理
	bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

首先会调用beforePrototypeCreation方法将当前线程正在创建的Bean的名称添加到线程私有的集合prototypesCurrentlyInCreation中,以便于检测到循环依赖。随后,同样会调用createBean创建实例,然后检查这个Bean实例是不是属于FactoryBean并进行相应处理,实例创建完成后会将prototypesCurrentlyInCreation中的变量删除,表示创建完成。

(3)其他作用域

else {
	//寻找其定义的作用域Scope接口
	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, () -> {
			//和Prototype作用域的处理类似
			beforePrototypeCreation(beanName);
			try {
				return createBean(beanName, mbd, args);
			} finally {
				afterPrototypeCreation(beanName);
			}
		});
		//检查这个Bean是不是FactoryBean,并进行相应处理
		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);
	}
}

对于其它作用域的Bean而言,BeanFactory首先会尝试从scopes找到对应的Scope对象(Scope接口定义了作用域的具体表现),如果没有找到则抛出IllegalStateException异常。找到Scope对象后会调用其get方法传入Bean的名称和ObjectFactory对象构造其对应的Bean实例,其余过程和Prototype作用域处理过程类似。

10、检查requiredType
if (requiredType != null && !requiredType.isInstance(bean)) {	//检查实际Bean的类型是否就是requiredType
	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());
	}
}

这一步骤比较简单,如果用户传入了requiredType的话,那么会检查Bean的类型是否符合requiredType,如果符合,则进行强制转换后返回给用户。如果不符合,则尝试通过TypeConverter进行类型的转换,如果无法转换那么会发生异常。

经过上述十个步骤,我们需要Bean就正式创建好了。

创建Bean的实例

回到刚才的第九个步骤,在传入ObjectFactory参数时,都会调用到一个方法createBean,该方法会将RootBeanDefinition转换为我们需要的实例。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;
	//正式加载Bean的Class
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		//克隆一个RootBeanDefinition,防止在此期间有其它线程进行动态解析
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	try {
		//验证覆盖的方法(lookup-method和replace-method指定的方法)
		mbdToUse.prepareMethodOverrides();
	} catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		//判断需不需要产生代理对象,也就是AOP。如果仅仅只是生成这个Class的对象,那么无需生成动态代理对象,此时就会返回null
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	} catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		//正式构造Bean的对象
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		throw ex;
	} catch (Throwable ex) {
		throw new BeanCreationException(
			mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

在构造对象前,会首先对这个Bean的进行类加载操作。随后,如果这个Bean定义了方法替换、方法拦截等属性,会启用AOP进行动态代理生成一个代理Bean然后返回。如果没有定义这些属性,则会调用doCreateBean生成对象:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) { //如果是单例,那么就尝试清空缓存
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		//构造BeanWrapper对象
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			} catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}
	//是否需要提早曝光
	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");
		}
		//添加到singletonFactories缓存
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	Object exposedObject = bean;
	try {
		//对bean进行填充,注入属性值,如果依赖于其它bean,则会递归初始依赖bean
		populateBean(beanName, mbd, instanceWrapper); 
		//调用初始化方法,例如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);
		if (earlySingletonReference != null) {	//只有当检测到循环依赖的时候才不会为null
			if (exposedObject == bean) {	//如果exposedObject没有在初始化方法中被改变
				exposedObject = earlySingletonReference;
			} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}
	try {
		//根据scope注册bean
		registerDisposableBeanIfNecessary(beanName, bean, mbd); 
	} catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}
	return exposedObject;
}

上述方法的实现思路如下:
1、如果Bean为单例首先要清除BeanWrapper缓存。
2、实例化Bean,并将对象和BeanDefinition信息合并到一个BeanWrapper实例。
3、获取BeanFactory所有的BeanPostProcessor并依次对这个Bean实例进行处理。诸如@Autowired注解的实现就是在这里进行的。
4、对该Bean进行依赖处理。
5、将该Bean所有的属性填充到实例中,并初始化实例。
这里Bean的初始化操作会调用Bean指定的init-method,如果Bean还实现了Aware接口也会在这一步骤进行操作。
6、循环依赖的检查。Spring只能够解决Singleton作用域的Bean,对于其它作用域的Bean一旦检测到循环依赖便会抛出异常。
7、DisposableBean的注册。
例如Bean指定了destory-method方法后这里会进行注册以便在BeanFactory被销毁后能够被调用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值