Bean加载过程
Bean加载的功能实现远比bean的解析要复杂的多了,对于加载bean的功能,在Spring中调用方式为:
/**
* <p>
* 此抽象基类为 {@link org.springframework.beans.factory.BeanFactory} 的实现提供了
* {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI 的全部功能。
* 它不假设可列举的 bean 工厂:因此也可作为从后端资源获取 bean 定义(其中 bean 定义访问是昂贵的操作)的 bean 工厂实现的基类。
* </p>
*
* <p>
* 该类提供 singleton 缓存(通过其基类
* {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry})、
* 单例/原型确定、{@link org.springframework.beans.factory.FactoryBean} 处理、别名、bean 定义合并用于子 bean 定义、
* 以及 bean 销毁(通过实现
* {@link org.springframework.beans.factory.DisposableBean} 接口和自定义销毁方法)。
* 此外,它还可以管理 bean 工厂层次结构(在未知 bean 的情况下委托给父 bean 工厂),通过实现
* {@link org.springframework.beans.factory.HierarchicalBeanFactory} 接口。
* </p>
*
* <p>
* 子类需要实现的主要模板方法是
* {@link #getBeanDefinition} 和 {@link #createBean},用于获取给定 bean 名称的 bean 定义和根据给定的 bean 定义创建 bean 实例。
* 在
* {@link DefaultListableBeanFactory} 和 {@link AbstractAutowireCapableBeanFactory} 中可以找到这些操作的默认实现。
* </p>
*/
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
//---------------------------------------------------------------------
// 实现 BeanFactory 接口
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
/**
* 返回指定 bean 的一个实例,该实例可以是共享的或独立的。
*
* @param name bean 的名称
* @param requiredType 要检索的 bean 的所需类型
* @param args 在使用显式参数创建 bean 实例时使用的参数
* (仅在创建新实例时应用,而不是检索现有实例时)
* @return bean 的实例
* @throws BeansException 如果无法创建 bean
*/
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {
return doGetBean(name, requiredType, args, false);
}
getBean函数会调用doGetBean函数获取Bean实例,这个函数是一个BeanFactory中的方法,用于获取指定的bean实例。它可以接受bean的名称、所需的类型、参数和一个类型检查标志。根据参数的不同,它可能从缓存中返回实例、创建一个新的实例或者委托给父BeanFactory来获取实例。最后,它会适配bean实例并返回。如果发生异常,将抛出BeansException异常。代码如下:
/**
* 返回一个实例,该实例可以是共享的或独立的,具体取决于传入的参数。
*
* @param name 要获取的bean的名称
* @param requiredType 需要的bean的类型
* @param args 创建一个使用显式参数的bean实例时使用的参数
* @param typeCheckOnly 是否获取bean实例进行类型检查,而不是实际使用
* @return 生成的bean实例
* @throws BeansException 如果无法创建bean,则抛出BeansException异常
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 提取对应的beanName
String beanName = transformedBeanName(name);
Object beanInstance;
/**
* 检查缓存中或者实例工厂中是否有对应的实现
* 为什么首先会使用这段代码呢?因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的
* 时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory
* 加入到缓存中,这样其他Bean在创建时如果依赖这个Bean,就直接使用ObjectFactory
*/
// 检查共享缓存中手动注册的单例bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("返回被提前缓存的单例bean实例,该实例尚未完全初始化 - 作为循环引用的结果");
}
else {
logger.trace("返回被缓存的单例bean实例");
}
}
// 返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身
// 而是返回指定方法返回的实例
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 只有在单例情况才会尝试解决循环依赖,原型模式情况下,如果存在A中有B的属性,B中有A的
// 属性,那么当依赖注入的时候,就会产生A还未创建完成的时候,因为对于B的创建再次返回创
// 建A,造成循环依赖,即isPrototypeCurrentlyInCreation(beanName)为true。
// 如果我们在创建这个bean实例时已经创建了,那么很可能是循环引用。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查bean定义是否存在于当前工厂中。如果工厂不为空,且IOC容器里面不包含这个bean
//一般来说只要配置正确是不会走这里的,这里是针对在bean标签中引用了其他bean,但其他bean并没有实例化
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 未找到 - 在父工厂中进行检查。
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 将其传递给父工厂并使用显式参数创建新的实例。
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// 没有参数 - 通过标准getBean方法进行委托。
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不是仅仅做类型检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,
// 如果指定BeanName是子Bean的话同时会合并父类的相关属性
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 保证当前bean所依赖的bean的初始化。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// isDependent用于判断指定的依赖bean是否已被注册为给定bean的依赖,
// 或者是否依赖于给定bean的任何传递依赖。
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"循环依赖关系 - '" + beanName + "' 与 '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// 获取依赖的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' 依赖缺失的bean '" + dep + "'", ex);
}
}
}
// 创建bean实例。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 显式地从单例缓存中删除实例 - 可能会被创建过程中的循环引用分辨率所放置。
// 同时删除任何接收临时引用的bean实例。
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 这是一个prototype - 创建一个新的实例。
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("未定义bean的scope名字:'" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("未注册scope名字:'" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
if (!isCacheBeanMetadata()) {
clearMergedBeanDefinition(beanName);
}
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
从上面的代码可以看出来bean的加载经历了一个相当复杂的过程,其中涉及各种各样的处理。对于加载过程涉及transformedBeanName
1、转换对应beanName
transformedBeanName传入的参数可能是别名、也可能是FactoryBean,所以需要进一步的解析,这些解析内容包括如下内容:
- 去除FactoryBean的修饰符,也就是如果name="&&aa",那么首先去除&而使name="aa"。
- 取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B;若别名A指向别名B,别名B又指向名称为C的bean则返回C。
2、尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等Bean创建完成就会将创建Bean的ObjectFactory提前加入到缓存中,一旦下一个bean创建的时候需要依赖上一个bean,则直接使用ObjectFactory。
3、Bean的实例化
如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里必须要强调一下,缓存中记录的只是原始的bean状态,并不一定是我们最终想要的bean。
4、原型模式的依赖检查
只有在单例模式下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生A还未创建完成的时候,因为对于B的创建再次返回创建A,造成循环依赖,即isPrototypeCurrentlyInCreation(beanName)为true。代码如下:
5、检测parentBeanFactory
其中containsBeanDefinition是在检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下了,然后再去递归的调用getBean方法,代码如下:
// 检查bean定义是否存在于当前工厂中。
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 未找到 - 在父工厂中进行检查。
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 将其传递给父工厂并使用显式参数创建新的实例。
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// 没有参数 - 通过标准getBean方法进行委托。
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
6、将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
因为从XML配置文件中读取到的bean信息是存储到GernericBeanDefinition中的,但是所有的bean后续处理都是针对于RootBeanDefinition的,所以这里需要一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性。代码如下:
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
7、寻找依赖
因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺序中,在初始化某一个bean的时候首先初始化这个bean所对应的依赖。代码如下:
// 保证当前bean所依赖的bean的初始化。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// isDependent用于判断指定的依赖bean是否已被注册为给定bean的依赖,
// 或者是否依赖于给定bean的任何传递依赖。
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"循环依赖关系 - '" + beanName + "' 与 '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// 获取依赖的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' 依赖缺失的bean '" + dep + "'", ex);
}
}
}
8、针对不同的scope进行bean的创建
在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他的配置,诸如prototype、request之类的,在这个步骤中,Spring会根据不同的配置进行不同的初始化策略。代码如下:
// 创建bean实例。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 显式地从单例缓存中删除实例 - 可能会被创建过程中的循环引用分辨率所放置。
// 同时删除任何接收临时引用的bean实例。
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// 这是一个prototype - 创建一个新的实例。
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("未定义bean的scope名字:'" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("未注册scope名字:'" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
9、类型转换
通常对该方法的调用参数requiredType是为空的,但是可能存在这样的情况,返回的bean其实是个String,但是requiredType却是Integer的类型,那么这时候本步骤就会起作用了,它的功能就是将返回的bean转换为requiredType所指定的类型。代码如下:
return adaptBeanInstance(name, beanInstance, requiredType);
FactoryBean的使用
一般情况下,Spring通过反射机制利用Bean的class属性指定实现类来实例化Bean。Spring提供了一个FactoryBean的工厂类接口,用户可以通过实现该接口定制化Bean的逻辑。代码逻辑如下:
/**
* 接口FactoryBean是用来在`{BeanFactory}`中创建对象的工厂,它本身也是一个工厂。
* 如果一个bean实现了这个接口,它就会被用作对象工厂,而不是直接被用作bean实例。
* 这个接口用于支持单例和原型的设计模式。如果这个FactoryBean在调用时还没有完全初始化(例如因为它涉及到一个循环引用),则抛出相应的FactoryBeanNotInitializedException异常。
* 从Spring 2.0开始,FactoryBeans可以返回null对象,工厂将考虑这是一个正常值并使用它,而不再抛出FactoryBeanNotInitializedException。
* FactoryBean实现现在被鼓励适当地自己抛出FactoryBeanNotInitializedException。
* 返回bean的实例(可以是null)并可能抛出异常。在初始化过程中,不要依赖于创建的对象状态;
* 如果可用,仍然可以使用该状态。
*/
public interface FactoryBean<T> {
/**
* 一个属性的名称,可以被设置在一个 {@link org.springframework.beans.factory.config.BeanDefinition} 上
* 以便于工厂bean可以信号化当他们的对象类型无法从工厂bean类中推断出来的时候。
* @since 5.2
*/
String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
/**
* 返回bean的类型,如果不可用则返回null。
* 用于在装配期间检查特定类型的bean是否可用,例如在自动装配期间。
* 在创建一个单例对象时,此方法应尽可能避免创建单例对象;它应该提前估计类型。
* 对于原型,返回一个有意义的类型也是可取的。
* 此方法可以在FactoryBean被完全初始化之前调用。
* 它不能依赖于初始化期间创建的状态;如果可用,仍然可以使用该状态。
* 自动装配将简单地忽略返回null的FactoryBeans;
* 因此,建议正确实现此方法,使用FactoryBean的当前状态。
* @return bean的类型,或者如果在调用时不可用,则为null
* @see ListableBeanFactory#getBeansOfType
*/
Class<?> getObjectType();
/**
* 返回一个对象(可以是null),可能会抛出异常。
* @return 新创建的对象(可以是null)
* @throws Exception 在创建对象时发生错误
*/
@Nullable
T getObject() throws Exception;
/**
* 是由这个工厂创建的对象单例吗?也就是说,`{getObject()}`始终返回同一个对象(可以缓存的引用)吗?
* <p>**注意:**如果FactoryBean指示持有单例对象,则从`{getObject()}`返回的对象
* 可能会被拥有者的BeanFactory缓存。
* 因此,只有在FactoryBean始终显示地返回相同引用时才返回`{true}`。
* FactoryBean自身的单例状态通常由拥有者提供的BeanFactory提供。
* 通常,它必须在那边定义为单例。
* <p>**注意:**如果此方法返回`{false}`,并不一定表示返回的对象是独立的实例。
* `SmartFactoryBean`接口的扩展实现可以显式地指示独立实例。
* 未实现此扩展接口的plain `FactoryBean`实现如果`{isSingleton()}`实现返回`{false}`
* 则简单地假设返回独立实例。
* <p>默认实现返回`{true}`,因为`{FactoryBean}`通常管理一个单例实例。
* @return 如果暴露的对象是单例,则返回`{true}`
* @see #getObject()
* @see SmartFactoryBean#isPrototype()
*/
default boolean isSingleton() {
return true;
}
}
缓存中获取单例Bean
单例在Spring的同一个容器内只会被创建一次,后续再获取Bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载。因为在创建单例的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等Bean创建完成就会将创建Bean的ObjectFactory提前加入到缓存中,一旦下一个bean创建的时候需要依赖上一个bean,则直接使用ObjectFactory。代码如下:
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
/**
* 返回注册在给定名称下的原始单例对象。
* <p>检查已经实例化的单例对象,并且还允许引用当前正在创建的单例对象(解决循环引用)。
* @param beanName 要查找的bean的名称
* @param allowEarlyReference 是否允许创建早期引用
* @return 注册的单例对象,如果未找到则返回null
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 快速检查是否存在实例而不获取完整的单例锁
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 在完整单例锁内一致创建早期引用
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
这个方法首先尝试从singletonObjects里面获取实例,如果取不到再从earlySingletonObjects里面获取,如果还取不到则尝试从singletonFactories获取ObjectFactory,然后再调用这个ObjectFactory的getObject()函数来创建bean,并放到earlySingletonObjects中,并从singletonFactories中remove这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是allowEarlyReference为true的时候才会使用。
getSingleton函数还可以根据指定的bean名称和ObjectFactory获取Bean实例,这个方法首先尝试从singletonObjects里面获取实例,如果取不到再调用这个ObjectFactory的getObject()函数来创建bean。代码如下:
/**
* 返回注册在给定名称下的原始单例对象,如果尚未注册,则创建并注册一个新的对象。
* @param beanName 贝恩对象的名称
* @param singletonFactory 用于在需要时延迟创建单例对象的ObjectFactory对象
* @return 注册的单例对象
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
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 + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
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;
}
}
从Bean的实例中获取对象
在getBean方法中,getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获取Bean还是根据不同的scope策略加载Bean。总之,我们得到Bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前Bean是否是FactoryBean类型的Bean,如果是那么需要调用该Bean对应的FactoryBean实例中的getObject()作为返回值。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getObjectForBeanInstance代码如下:
/**
* 重写此方法以在程序matically在{@link Supplier}回调期间获取进一步的bean时将当前创建的bean注册为dependent。
* @since 5.0
* @see #obtainFromSupplier
*/
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
基类org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance源码如下:
/**
* 获取给定bean实例的对象,该对象可以是bean实例本身或者是FactoryBean创建的对象。
* @param beanInstance 共享的bean实例
* @param name 可能包含工厂引用前缀的名称
* @param beanName 规范的bean名称
* @param mbd 合并后的bean定义
* @return 要公开的bean对象
*/
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(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 现在我们有了bean实例,它可能是一个普通bean或FactoryBean。
// 如果它是FactoryBean,我们使用它来创建一个bean实例,除非调用者实际上想要一个工厂引用。
if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {
return beanInstance;
}
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中加载Bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 从工厂返回bean实例。
// 如果工厂是单例,则缓存FactoryBean获取的实例。
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否是用户定义的而不是引用程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);
}
return object;
}
上述代码最终将从Factory解析Bean的工作委托给getObjectFromFactoryBean。该函数从给定的FactoryBean中获取对象。如果FactoryBean是单例且已经存在缓存中,则直接返回。否则,它会调用FactoryBean的getObject()方法来获取对象,并根据需要进行后处理。如果存在循环依赖,则可能会在获取对象期间重复获取对象,所以需要检查并处理这种情况。最后,根据是否为单例对象,在缓存中存储对象。
/**
* 从给定的FactoryBean获取对象
* @param factory FactoryBean实例
* @param beanName Bean的名称
* @param shouldPostProcess 是否对Bean进行后处理
* @return 从FactoryBean中获取的对象
* @throws BeanCreationException 如果FactoryBean对象创建失败
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
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);
// 只有在上面的getObject()调用中没有放入时才进行后处理和存储
// (例如,因为自定义getBean调用触发的循环引用处理)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// 临时返回未后处理的单例对象,尚未存储...
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"FactoryBean的单例对象的后处理失败", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean对象的后处理失败", ex);
}
}
return object;
}
}
其中doGetObjectFromFactoryBean函数用于从给定的FactoryBean中获取对象。它首先尝试调用FactoryBean.getObject()方法获取对象,如果抛出FactoryBeanNotInitializedException异常,则抛出BeanCurrentlyInCreationException异常;如果抛出其他异常,则抛出BeanCreationException异常。如果获取的对象为null,则判断是否FactoryBean正在创建中,如果是,则抛出BeanCurrentlyInCreationException异常;否则,创建一个NullBean对象并返回。
/**
* 从给定的FactoryBean获取要暴露的对象。
*
* @param factory FactoryBean实例
* @param beanName 被引用对象的名称
* @return 从FactoryBean获取的对象
* @throws BeanCreationException 如果FactoryBean对象创建失败
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
object = factory.getObject();
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean在对象创建时抛出了异常", ex);
}
// 对于尚未完全初始化的FactoryBean,不接受一个null值:
// 许多FactoryBean只是在getObject时返回null。
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "正在创建中的FactoryBean从getObject返回了null");
}
object = new NullBean();
}
return object;
}
getObjectFromFactoryBean函数在调用doGetObjectFromFactoryBean获取到Bean后会调用postProcessObjectFromFactoryBean进行进一步的操作。
/**
* 对注册的BeanPostProcessors中的每个BeanPostProcessor应用`postProcessAfterInitialization`回调方法,
* 给它们一个机会来处理从FactoryBeans获取的对象(例如,自动代理)。
* @see #applyBeanPostProcessorsAfterInitialization
*/
@SuppressWarnings("deprecation")
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
/**
* 应用初始化后对bean进行后处理
*
* @param existingBean 存在的bean对象
* @param beanName bean名称
* @return 后处理结果
* @throws BeansException 如果在后处理过程中出现异常,抛出BeansException异常
* @since 6.1
*/
@Deprecated(since = "6.1")
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
回到getObjectFromFactoryBean函数中,其在单例模式下,会调用postProcessObjectFromFactoryBean前后会分别调用beforeSingletonCreation和afterSingletonCreation,部分源码如下:
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);
}
beforeSingletonCreation函数的逻辑很简单,主要是记录加载状态,即通过singletonsCurrentlyInCreation.add(beanName)将当前正在创建的bean记录到缓存中,这样便于对循环依赖进行检测。如果singletonsCurrentlyInCreation已经有了指定的beanName,再添加该beanName就会抛出BeanCurrentlyInCreationException异常错误。
/**
* 在创建单例之前调用的回调方法。
* <p>
* 默认实现会将该单例注册为正在创建状态。
* @param beanName 即将被创建的单例的名称
* @see #isSingletonCurrentlyInCreation
*/
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
当bean加载结束后就会调用afterSingletonCreation函数将当前的beanName从singletonsCurrentlyInCreation移除,源码如下:
/**
* 在单例创建后的回调方法。
* <p>
* 默认实现将该单例标记为不再处于创建状态。
* @param beanName 已创建的单例的名称
* @see #isSingletonCurrentlyInCreation
*/
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
关于Bean的创建,请参考Spring源码解析——创建Bean