目录
一、概要
二、getBean(String name):获取指定名称的bean
三、总结
一、概要
通过前面几篇文章对IOC容器创建流程的详细分析,相信大家对IOC有了一个全新的认识,但是我们还不知道Spring如何获取Bean实例的,本篇文章,我们就关于获取 Bean 实例的过程做一个比较详细的分析。
二、getBean(String name):获取指定名称的bean
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)方法主要用于从bean工厂中获取指定名称的bean实例,如果获取不到,将会执行实例化、属性填充、初始化等一系列过程。
首先来看看getBean(String name)方法的定义:
// org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
public Object getBean(String name) throws BeansException {
// 真正获取bean的方法
return doGetBean(name, null, null, false);
}
getBean()方法内部通过doGetBean()执行真正获取bean,大体过程如下:
- 第一步:转换bean的名称,包括去除FactoryBean引用前缀“&”,如果是别名就需要找到它最终指向的beanName;
- 第二步:尝试从缓存中获取对应的bean;
- 第三步:返回beanName对应的实例对象,内部包含对FactoryBean的处理;
- 第四步:如果在当前工厂中获取不到bean实例,则获取到父容器,如果不存在当前beanName对应的bean定义信息,则尝试从父容器获取对应的bean;
- 第五步:将指定的 bean 标记为已创建(或即将创建);
- 第六步:返回bean定义信息;
- 第七步:获取到当前bean依赖的bean名称集合,保证当前bean依赖的bean的初始化;
- 第八步:尝试从缓存中获取对应的bean实例,获取不到的话,则执行singletonFactory的回调 -> createBean()创建bean实例,并添加到缓存中;
- 第九步:检查所需类型是否与实际 bean 实例的类型匹配;
- 第十步:返回上述创建好的bean实例对象;
doGetBean()方法源码如下:
protectedT doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 1、第一步:转换bean的名称,包括去除FactoryBean引用前缀“&”;如果是别名就需要找到最终指向的beanName String beanName = transformedBeanName(name); Object bean; // 2、第二步:尝试从缓存中获取对应的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 + "'"); } } // 如果存在手动注册的单例 // 3、第三步:返回beanName对应的实例对象,内部包含对FactoryBean的处理 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 如果不存在手动注册的单例 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // Spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”中,bean在创建过程中将一直保持在这个池中, // 如果在创建bean过程中发现自己已经在“当前创建bean池”中,将抛出BeanCurrentlyInCreationException异常,表示发生了循环依赖。 // bean创建完毕后,将会从“当前创建bean池”中移除掉 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. // 4、第四步:获取到父容器,如果不存在当前beanName对应的bean定义信息,则尝试从父容器获取对应的bean // 获取父容器 BeanFactory parentBeanFactory = getParentBeanFactory(); // 如果存在父容器,并且在当前工厂中不存在当前beanName对应的Bean定义信息,则尝试从父容器中获取bean实例 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); } } // 5、第五步:将指定的 bean 标记为已创建(或即将创建) if (!typeCheckOnly) { // 如果不是仅仅做类型检测,则将指定的 bean 标记为已创建(或即将创建) // private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)) // 也就是将beanName存入上述alreadyCreated集合中 markBeanAsCreated(beanName); } try { // 6、第六步:返回bean定义信息 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 校验bean定义信息,如果是抽象的,则抛异常BeanIsAbstractException checkMergedBeanDefinition(mbd, beanName, args); // 7、第七步:获取到当前bean依赖的bean名称集合,保证当前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 + "'"); } // 如果BeanDefinition有依赖,就先把依赖关系注册到容器的dependentBeanMap缓存,再递归加载依赖的bean registerDependentBean(dep, beanName); try { // 先实例化当前bean依赖的其他bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 单例bean的创建 if (mbd.isSingleton()) { //单例作用域 // 第二个参数是一个ObjectFactory,是一个函数式接口,当调用ObjectFactory的getObject()方法的时候,实际上调用的是createBean(beanName, mbd, args) // 也就是说在getSingleton()方法内部调用ObjectFactory的getObject()方法的时候,会回调到这里的createBean(beanName, mbd, args)创建bean,接着才会调用下面的getObjectForBeanInstance()方法 // 8、第八步:尝试从缓存中获取对应的bean实例,获取不到的话,则执行singletonFactory的回调 -> createBean()创建bean sharedInstance = getSingleton(beanName, () -> { try { // 创建bean对象 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. // 创建失败则销毁bean destroySingleton(beanName); throw ex; } }); // 返回beanName对应的实例对象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { //多例bean的创建 Object prototypeInstance = null; try { // 多例bean创建前的操作:保存beanName到prototypesCurrentlyInCreation缓存中(为了防止循环依赖) // private final ThreadLocal
下面对一些比较重要的方法做一下分析:
- transformedBeanName(name):转换bean的名称,必要时去除FactoryBean引用前缀“&”,如果是别名就去寻找它最终指向的beanName;
// 返回 bean 名称,包括去除FactoryBean引用前缀,并将别名解析为真正的bean名称
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 如果name不是以&开头,则直接返回,无需处理
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 如果name以&开头,则需要处理,获取到实际的bean名称
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
// 截取掉FactoryBean的前缀&
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
// org.springframework.core.SimpleAliasRegistry#canonicalName
// 确定bean原始名称,将别名解析为真正的bean名称
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 处理别名
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while (resolvedName != null);
return canonicalName;
}
- getSingleton(beanName):尝试从缓存中获取对应的bean
getSingleton()方法是Spring中用来解决循环依赖的核心代码,涉及到三级缓存、提前暴露对象等,后面我们单独用一篇文章总结Spring是如何解决循环依赖的。
getSingleton()方法大体过程如下:
- 第一步:从一级缓存中(singletonObjects)中尝试获取;
- 第二步:如果一级缓存没有获取到,就从提早曝光单例对象(earlySingletonObjects)二级缓存中尝试获取;
- 第三步:如果二级缓存中还没有,就从singletonFactories(三级缓存)中尝试获取这个bean的ObjectFactory对象工厂,再调用ObjectFactory.getObject()获取到bean,然后放入earlySingletonObjects二级缓存中,把ObjectFactory从singletonFactories(三级缓存)中移除;
getSingleton()源码如下:
// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) {
// 尝试从缓存中加载bean对象
// 第二个参数:表示是否允许bean早期依赖
// 调用重载的getSingleton()方法
return getSingleton(beanName, true);
}
// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
// Spring 解决循环引用的核心代码
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 尝试从一级缓存中获取对应的bean对象
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一级缓存中不存在,并且当前单例bean处于正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果一级缓存中没有的话,再尝试从二级缓存中获取对应的bean对象
// 从早期单例对象缓存earlySingletonObjects中获取单例对象(之所称为早期单例对象,是因为earlySingletonObjects里的对象的都是通过提前曝光的ObjectFactory对象工厂创建出来的,还未进行属性填充等操作)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 加锁
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 如果二级缓存中也没有的话,再尝试从三级缓存中获取对应的ObjectFactory单例工厂
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
// 如果存在单例工厂,则调用单例工厂ObjectFactory的getObject()方法,创建一个bean
if (singletonFactory != null) {
// 调用ObjectFactory的getObject()方法,产生一个半成品bean
// 因为添加三级缓存的时候执行的是: addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)),
// 所以singletonFactory.getObject()真正执行的其实是:获取bean的早期引用 ===> getEarlyBeanReference(beanName, mbd, bean)
singletonObject = singletonFactory.getObject();
// 将bean放置于二级缓存中(放到早期单例对象缓存中)
this.earlySingletonObjects.put(beanName, singletonObject);
// 删除三级缓存中对应bean的单例工厂ObjectFactory
// 因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存(二级缓存)中了,所以后面获取beanName的单例对象的时候,
// 可以从earlySingletonObjects二级缓存拿到,不需要再用到该单例工厂
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
// 返回单例对象
return singletonObject;
}
Spring循环依赖涉及到三个缓存,这里先简单介绍一下:
- singletonObjects:一级缓存,它用于存放初始化好的 bean 实例;
- earlySingletonObjects:二级缓存,它用于存放初始化中的 bean,此时的bean是一个半成品,提前暴露的对象都放在这里,Spring利用它来解决循环依赖;
- singletonFactories:三级缓存,它用于存放生成bean的对象工厂,注意bean 工厂所生成的 bean 还没有完成初始化;
- getObjectForBeanInstance(sharedInstance, name, beanName, null):返回beanName对应的实例对象
getObjectForBeanInstance()大体流程如下:
- 第一步:判断name是否以“&”为前缀;
- 第二步:如果name以“&”为前缀,但是又不是一个FactoryBean的话,则会抛出BeanIsNotAFactoryException异常;
- 第三步:如果beanInstance不是FactoryBean,则直接返回beanInstance;如果name以“&”为前缀,并且beanInstance是FactoryBean的话,表示希望获取到工厂bean对象,则直接返回beanInstance;
- 第四步:beanInstance是FactoryBean,并且name不是以“&”为前缀,表示希望获取到工厂帮我们创建的bean对象,则需要执行FactoryBean的getObject()方法帮我们创建对应的bean实例;
// org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 1、判断name是不是以“&”为前缀
// 判断逻辑在isFactoryDereference()方法
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 2、如果name以“&”为前缀,但是又不是一个FactoryBean的话,则会抛出BeanIsNotAFactoryException异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
// 现在我们有了 bean 实例,它可能是普通 bean 或 FactoryBean.
// 如果它是一个FactoryBean,我们用它来创建一个 bean 实例,除非调用者实际上想要一个对工厂的引用
// 3、如果beanInstance不是FactoryBean,则直接返回beanInstance;如果name以“&”为前缀,并且beanInstance是FactoryBean的话,则直接返回beanInstance;
// !(beanInstance instanceof FactoryBean): 如果beanInstance不是FactoryBean,则直接返回beanInstance
// BeanFactoryUtils.isFactoryDereference(name): 如果name以“&”为前缀,并且beanInstance是FactoryBean的话,则直接返回beanInstance
// 前面已经介绍过,如果bean实现了FactoryBean结果,并且通过getBean(&beanName)获取bean的话,则获取的是FactoryBean本身
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 4、beanInstance是FactoryBean,并且name不是以“&”为前缀,表示需要执行FactoryBean的getObject()方法帮我们创建对应的bean实例
Object object = null;
if (mbd == null) {
// 如果mdb为空,尝试从factoryBeanObjectCache缓存中获取FactoryBean创建的对象实例
// 如果缓存中存在对象实例,则直接返回object
object = getCachedObjectForFactoryBean(beanName);
}
// 缓存中不存在对应的对象实例
if (object == null) {
// Return bean instance from factory.
FactoryBean> factory = (FactoryBean>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 从FactoryBean中获取对应的对象实例,底层实际上是执行FactoryBean的getObject()方法
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
- BeanFactoryUtils.isFactoryDereference(name):判断name是否以&为前缀
// org.springframework.beans.factory.BeanFactoryUtils#isFactoryDereference
public static boolean isFactoryDereference(@Nullable String name) {
// 判断name是否以&为前缀
// String FACTORY_BEAN_PREFIX = "&";
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
- getObjectFromFactoryBean():从给定的 FactoryBean 获取要公开的对象
// 从给定的 FactoryBean 获取要公开的对象
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean> factory, String beanName, boolean shouldPostProcess) {
// 如果是单例的,并且beanName已经在singletonObjects单例缓存池中
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 尝试从FactoryBean创建的单例对象的缓存factoryBeanObjectCache中获取bean实例
Object object = this.factoryBeanObjectCache.get(beanName);
// 缓存factoryBeanObjectCache中获取bean实例为空,则执行doGetObjectFromFactoryBean()创建bean实例
if (object == null) {
// 这里真正执行FactoryBean的getObject()方法创建bean
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;
}
// 单例创建前的准备:将beanName添加到singletonsCurrentlyInCreation缓存中
beforeSingletonCreation(beanName);
try {
// 执行BeanPostProcessor的postProcessAfterInitialization()方法
// 具体参考:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
} finally {
// 单例创建完成后的工作:移除singletonsCurrentlyInCreation中对应的beanName缓存
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
// 将beanName和object放到factoryBeanObjectCache缓存中,这样下来再次获取,就可以从缓存中获取,无需重复创建
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
// 如果缓存factoryBeanObjectCache中获取bean实例不为空,则直接返回
return object;
}
} else {
// 非单例的
// 这里真正执行FactoryBean的getObject()方法创建bean
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
// 后置增强
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
- doGetObjectFromFactoryBean():真正执行FactoryBean的getObject()方法创建bean
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(FactoryBean> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
// 执行FactoryBean的getObject()方法
object = AccessController.doPrivileged((PrivilegedExceptionAction
- postProcessObjectFromFactoryBean(object, beanName):执行后置增强
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#postProcessObjectFromFactoryBean
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
return object;
}
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 执行BeanPostProcessor的后置增强方法postProcessAfterInitialization()
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
- markBeanAsCreated(beanName):将指定的 bean 标记为已创建
// 将指定的 bean 标记为已创建
protected void markBeanAsCreated(String beanName) {
// private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256))
// 如果alreadyCreated缓存中不包含指定的beanName
if (!this.alreadyCreated.contains(beanName)) {
// 加锁,避免BeanDefinition发生变化
synchronized (this.mergedBeanDefinitions) {
// 再一次判断
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
// 实际上执行this.mergedBeanDefinitions.remove(beanName):移除缓存mergedBeanDefinitions中beanName对应的bean定义信息
// 为了后面的代码重新获取时,能使用到最新的MergedBeanDefinition来创建bean实例
clearMergedBeanDefinition(beanName);
// 将beanName存入alreadyCreated缓存,标记bean为已创建
this.alreadyCreated.add(beanName);
}
}
}
}
从上图中我们也可以看到,在本例子中,student这个beanName已经被加入到alreadyCreated缓存中。
- getSingleton(String beanName, ObjectFactory> singletonFactory):尝试从缓存中获取对应的bean实例,获取不到的话,则执行singletonFactory的回调 -> createBean()创建bean
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 加锁,避免重复创建单例对象
synchronized (this.singletonObjects) {
// 尝试从一级缓存中获取对应的bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一级缓存中存在的话,则直接返回singletonObject
// 如果一级缓存中不存在的话,才进行singletonObject的创建
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正在加载的状态,将当前正要创建的bean记录在缓存singletonsCurrentlyInCreation中
// private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
beforeSingletonCreation(beanName);
// 是否是一个新的单例对象的标识
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new linkedHashSet<>();
}
try {
// 执行singletonFactory的回调,也就是FactoryBean真正帮我们创建对象的地方
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;
}
// 创建单例后的操作:通过this.singletonsCurrentlyInCreation.remove(beanName)移除bean正在加载状态的记录
// private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 如果是新的bean对象,则将bean保存到一级缓存(singletonObjects)、已注册bean缓存(registeredSingletons)中,同时删除二级缓存(earlySingletonObjects)、三级缓存(singletonFactories)中对应的bean信息
addSingleton(beanName, singletonObject);
}
}
// 返回处理结果
return singletonObject;
}
}
getSingleton(String beanName, ObjectFactory> singletonFactory)主要步骤:
- a、尝试从一级缓存中获取对应的bean,如果获取到,直接返回;如果获取不到,则执行singletonFactory.getObject()方法回调,从方法调用处可以看到,执行createBean()方法,这个方法也是非常重要的一个方法,里面包括了bean的实例化、初始化等,后面单独分析。
- b、创建单例前的操作,记录bean正在加载的状态,将当前正要创建的bean记录在缓存singletonsCurrentlyInCreation中;
- c、创建单例后的操作:通过this.singletonsCurrentlyInCreation.remove(beanName)移除bean正在加载状态的记录;
- d、如果是新的bean对象,则将bean保存到一级缓存(singletonObjects)、已注册bean缓存(registeredSingletons)中,同时删除二级缓存(earlySingletonObjects)、三级缓存(singletonFactories)中对应的bean信息;
来看几个关键方法的代码:
- beforeSingletonCreation():创建单例前的操作
protected void beforeSingletonCreation(String beanName) {
// inCreationCheckExclusions表示当前从创建检查中排除的bean的名称,通常情况下为空
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
如上图,本例中的student的beanName已经添加到singletonsCurrentlyInCreation缓存中了。
- afterSingletonCreation():创建单例后的操作
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
同理,beforeSingletonCreation()方法添加对应的缓存,那么afterSingletonCreation()创建完后续工作就是需要移除对应的缓存:
- addSingleton():添加bean到一级缓存中,方面后面直接获取
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 将bean保存到一级缓存中
this.singletonObjects.put(beanName, singletonObject);
// 删除三级缓存对应的bean
this.singletonFactories.remove(beanName);
// 删除二级缓存中对应的bean
this.earlySingletonObjects.remove(beanName);
// 记录当前所有已注册的bean
this.registeredSingletons.add(beanName);
}
}
三、总结
到这里,关于Spring中getBean()获取bean实例的核心流程基本上就介绍完了,我们可以看到,获取一个bean的流程还是比较复杂的,涉及到了非常多的流程。读者在学习过程中,可以多跟踪几次源代码,对一些特殊场景写一些示例代码调试,逐步了解Spring是如何获取bean实例的,慢慢地对getBean流程就没那么陌生了。
最后我们简述一下getBean()整体流程:
1、将name转化为真正的beanName,包括去除FactoryBean的前缀符&,将别名转换为真正beanName
2、通过getSingleton()方法尝试从缓存中获取指定的bean对象
2.1、先从一级缓存singletonObjects中查找;
2.2、如果一级缓存中在找不到的话,再尝试从二级缓存earlySingletonObjects(提早曝光单例缓存池)中查找;
2.3、如果二级缓存也找不到的话,则从三级缓存singletonFactories中查找ObjectFactory对象工厂,并生成对应的bean对象,然后放入earlySingletonObjects二级缓存中,
最后移除三级缓存中对应的ObjectFactory对象工厂;
3、如果缓存中都没有找到对应的bean,则需要新建一个bean
3.1、从当前容器中查找对应的BeanDefinition定义信息;
3.2、如果当前容器没找到,再从父容器中查找有没有BeanDefinition;
3.3、获取到BeanDefinition中定义的depends-on依赖的bean对象,递归加载的其依赖的bean对象;
3.4、根据不同的scope分别创建bean实例;
4、如果是FactoryBean,返回生产的bean
4.1、首先尝试从缓存factoryBeanObjectCache中获取;
4.2、如果获取的到,则直接返回,否则调用BeanFactory.getObject()生产一个bean实例;
4.3、如果不是应用程序本身的bean,调用后置处理器BeanPostProcessor的postProcessAfterInitialization()方法;
4.4、如果是单例的话存入factoryBeanObjectCache缓存中;



