# Spring
源码 - getObjectForBeanInstance()
Spring
版本:Spring 5.3.13-release
# 1、getObjectForBeanInstance()
- 检测FactoryBean<?>
在Spring
获取Bean
相关源码中,可以发现,每当Spring
尝试去获取或者创建一个Bean
实例的时候,一旦这个动作完成Spring
会立即调用getObjectForBeanInstance()
方法。这个方法看似不起眼,其实对于FactoryBean<?>
起着非常关键的作用。
因为之前已经写过FactoryBean<?>
相关的介绍文章,所以这里对于FactoryBean<?>
不做过多的介绍
AbstractBeanFactory#doGetBean()
方法片段:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
Object sharedInstance = getSingleton(beanName);
// 如果 Bean 的单例对象找到了, 并且没有创建实例时需要使用的参数
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 + "'");
}
}
// 返回对象的实例。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 源码过长, 此处省略部分源码
return adaptBeanInstance(name, beanInstance, requiredType);
}
正如上面所说的,Spring
在使用getSingleton()
方法尝试从缓存中获取Bean
之后,如果获取到的Bean
不为空就会立即调用getObjectForBeanInstance()
方法。Spring
为何要如此做,原因是因为当Spring
无论从哪种方式,哪种scope
获取Bean
实例之后,都需要对这个Bean
进行检查其是否是FactoryBean<?>
类型,如果这个Bean
是FactoryBean<?>
类型,则需要回调FactoryBean<?>
接口中定义的三个方法进行初始化开发者实现FactoryBean<?>
接口对特殊Bean
实施的高级定制初始化逻辑。
# 2、getObjectForBeanInstance()
检查FactoryBean<?>
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.
// 如果 BeanName 是 FactoryBean<?> 相关的 BeanName
if (BeanFactoryUtils.isFactoryDereference(name)) {
// BeanInstance 是 NullBean
if (beanInstance instanceof NullBean) {
// 直接返回 beanInstance
return beanInstance;
}
// 如果不是 FactoryBean<?> 类型的 Bean 实例
if (!(beanInstance instanceof FactoryBean)) {
// 抛出异常 : 当前 Bean 不是一个工厂
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
// 如果 BeanName 与 FactoryBean<?> 相关 && beanInstance 不是 NullBean
// && beanInstance 是 FactoryBean<?> 类型 && RootBeanDefinition 不为空
if (mbd != null) {
// 当前 Bean 实例为 FactoryBean<?> 类型的 Bean
mbd.isFactoryBean = true;
}
// 直接返回当前 Bean 实例, 这也是为什么针对于一个 FactoryBean<?> 类型的 Bean 实例而言
// 使用 '&' + beanName 就能获取到 FactoryBean<?> 本身
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
// 现在拥有了一个新的 BeanInstance, 这个实例可能是常规 Bean 也有可能是 FactoryBean<?>
// 如果是 FactoryBean<?> 则使用它创建实例, 但如果是开发者想要直接获取工厂实例而不是工厂的 getObject()
// 方法对应的实例, 那么传入的 BeanName 应该加入前缀 '&'
if (!(beanInstance instanceof FactoryBean)) {
// 如果不是 FactoryBean 直接返回当前 Bean 实例
return beanInstance;
}
// 如果是 FactoryBean
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 从缓存中加载
object = getCachedObjectForFactoryBean(beanName);
}
// 激活 FactoryBean<?> 的 getObject() 方法
if (object == null) {
// Return bean instance from factory.
// 这里已经明确知道 beanInstance 一定是 FactoryBean<?> 类型
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
// 如果 mbd 为空 && 从 XML 配置文件中加载的 BeanDefinition 中包含 BeanName 对应的 Bean 定义信息
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;
}
Spring
首先会判断当前beanName
是否是FactoryBean<?>
类型的BeanName
,FactoryBean<?>
类型的BeanName
是&
拼接上原始Bean
的BeanName
。即一个BeanName
为kapcb
的Bean
实现了FactoryBean<?>
接口,那么使用kapcb
就会从容器中获取到这个Bean
,如果需要获取FactoryBean
则需要使用&kapcb
从容器中获取。所以Spring
在对于Bean
的检查中第一步做的就是判断当前获取Bean
的BeanName
是否为FactoryBean<?>
的类型的BeanName
。如果获取的是FactoryBean<?>
类型的BeanName
则进行相关校验。如果确实是FactoryBean<?>
类型并且BeanDefinition
不为空,则修改该Bean
的BeanDefinition
中的isFactoryBean
属性为true
代表该Bean
是一个FactoryBean<?>
类型的Bean
,最后直接返回当前Bean
实例。节省性能开销,解析过一次后避免后面重复解析的性能开销。- 如果当前
beanName
不是FactoryBean<?>
类型的BeanName
,则判断当前Bean
实例是否是FactoryBean<?>
类型,如果不是FactoryBean<?>
类型则直接返回,说明该Bean
只是一个常规Bean
,则不需要后续处理直接返回。 - 如果当前
Bean
是FactoryBean<?>
类型,则说明当前获取的Bean
是实现FactoryBean<?>
接口的原始Bean
。则需要激活FactoryBean<?>
中定义的三个方法对当前Bean
进行实例化处理。
可以看到,上面的源码部分非常简单,对于FactoryBean<?>
类型Bean
的激活Spring
则是直接委派给了getObjectFromFactoryBean()
方法执行。
# 3、getObjectFromFactoryBean()
FactoryBeanRegistrySupport#getObjectFromFatoryBean()
源码:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 如果是单例 Bean && Bean 实例已经创建过, 没有再次创建的必要, 要保证单例 Bean 全局唯一, 直接从缓存中获取
if (factory.isSingleton() && containsSingleton(beanName)) {
// 进入同步代码块
synchronized (getSingletonMutex()) {
// 从缓存中获取
Object object = this.factoryBeanObjectCache.get(beanName);
// 如果缓存中没有
if (object == null) {
// 激活 FactoryBean<?> 中的 getObject() 方法获取开发者
// 定制的初始化逻辑
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 {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
可以看到,这部分源码也是非常简单。如果该FactoryBean<?>
实例是单例类型,那么就必须要保证Spring
中单实例Bean
的唯一以及使用缓存做到避免额外开销。并且Spring
在获取Bean
的规则中强调到,尽可能保证所有Bean
初始化之后都会激活容器中注册的BeanPostProcessor
中的postProcessorAfterBeanInitialization()
方法。而真正获取Bean
实例则是委托给了doGetObjectFromFactoryBean()
方法。
# 4、doGetObjectFromFactoryBean()
激活FactoryBean<?>
的getObject()
方法
FactoryBeanRegistrySupport#doGetObjectFromFactoryBean()
源码:
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, 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 {
// 激活 FactoryBean<?> 中的 getObject() 方法调用
// 开发者定制化的的 Bean 注册逻辑
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;
}
上面源码也是非常简单。激活FactoryBean<?>
接口中的getObject()
方法使用Bean
的定制初始化逻辑进行Bean
的初始化并返回。