警告
本文最后更新于 2020-11-28,文中内容可能已过时。
spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework 。
链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。
1 FactoryBean 的作用
Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean 即 FactoryBean。FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。创建出来的对象是否属于单例由isSingleton中的返回决定。
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean的形式
以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
2 FactoryBean 接口的定义
以下是 Spring 中 FactoryBean 接口的定义:
1
2
3
4
5
6
7
8
9
10
public interface FactoryBean < T > {
T getObject () throws Exception ;
Class <?> getObjectType ();
default boolean isSingleton () {
return true ;
}
}
3 应用场景
FactoryBean 通常是用来创建比较复杂的 bean,一般的 bean 直接用 xml 配置即可,但如果一个 bean 的创建过程中涉及到很多其他的 bean 和复杂的逻辑,用 xml 配置比较困难,这时可以考虑用 FactoryBean。
很多开源项目在集成 Spring 时都使用到 FactoryBean,比如 MyBatis3 提供 mybatis-spring 项目中的 org.mybatis.spring.SqlSessionFactoryBean:
1
2
3
4
5
<bean id= "sqlSessionFactory" class= "org.mybatis.spring.SqlSessionFactoryBean" >
<property name= "dataSource" ref= "dataSource" />
<!-- 自动扫描mapping.xml文件 -->
<property name= "mapperLocations" value= "classpath:mapper/*.xml" ></property>
</bean>
1
2
3
4
5
6
7
8
9
10
public class SqlSessionFactoryBean implements FactoryBean < SqlSessionFactory > , InitializingBean , ApplicationListener < ApplicationEvent > {
// ...
public SqlSessionFactory getObject () throws Exception {
if ( this . sqlSessionFactory == null ) {
this . afterPropertiesSet ();
}
return this . sqlSessionFactory ;
}
// ...
}
4 源码分析
4.1 初次创建
AbstractBeanFactory 通过 getBean 向 IOC 容器获取被管理的 Bean。
AbstractBeanFactory.getBean() -> doGetBean()。
来到 doGetBean(),看 bean 第一次创建实例后,调用的地方:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition ( beanName );
if ( mbd . isSingleton ()) {
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.
destroySingleton ( beanName );
throw ex ;
}
});
/*
TODO 重要程度 5
如果bean不是FactoryBean类型或者beanName以&开头,则直接返回。
否则调用FactoryBean的getObject(),且将返回的bean替换为getObject()的返回值。
FactoryBean接口很重要,具体应用场景见FactoryBean接口注释。
*/
bean = getObjectForBeanInstance ( sharedInstance , name , beanName , mbd );
}
}
可以看到,在 getSingleton()
之后,又调用了 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd)
,给 bean 重新赋值,这里bean的实例就可能被改变了。
如果当前创建的 bean 是 FactoryBean 类型的,调用 getObjectForBeanInstance()
时,最终会返回 FactoryBean.getObject()
返回的对象,也就是最终 getBean()
返回的是这个 getObject()
获取到的实例。
以下是 getObjectForBeanInstance()
的源码:
1
2
3
4
5
6
7
8
9
10
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
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 );
}
}
这里调用到了父类的方法,继续看父类的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected Object getObjectForBeanInstance (
Object beanInstance , String name , String beanName , @Nullable RootBeanDefinition mbd ) {
// ...
// 如果bean不是FactoryBean类型或者beanName以&开头,则直接返回。
if ( ! ( beanInstance instanceof FactoryBean ) || BeanFactoryUtils . isFactoryDereference ( name )) {
return beanInstance ;
}
Object object = null ;
// 如果BeanDefinition为null,从缓存中获取,doGetBean() 中传入的就是null
// createBean后进入这里的话,传入的就不是null
if ( mbd == null ) {
object = getCachedObjectForFactoryBean ( beanName );
}
if ( object == null ) {
FactoryBean <?> factory = ( FactoryBean <?> ) beanInstance ;
if ( mbd == null && containsBeanDefinition ( beanName )) {
mbd = getMergedLocalBeanDefinition ( beanName );
}
boolean synthetic = ( mbd != null && mbd . isSynthetic ());
// 调用FactoryBean的getObject方法
object = getObjectFromFactoryBean ( factory , beanName , ! synthetic );
}
return object ;
}
}
上面代码的尾部,调用到了 object = getObjectFromFactoryBean(factory, beanName, !synthetic)
,这个方法中调用了 getObject()。
源码如下(关键点 - 注意源码中高亮部分):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
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 ) {
// 调用 factory.getObject();
object = doGetObjectFromFactoryBean ( factory , beanName );
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 {
// 这里调用了BeanPostProcessor的后置处理
object = postProcessObjectFromFactoryBean ( object , beanName );
}
catch ( Throwable ex ) {
throw new BeanCreationException ( beanName ,
"Post-processing of FactoryBean's singleton object failed" , ex );
}
finally {
afterSingletonCreation ( beanName );
}
}
// 加入到缓存,缓存位置:BeanFactory的 factoryBeanObjectCache 成员中
if ( containsSingleton ( beanName )) {
this . factoryBeanObjectCache . put ( beanName , object );
}
}
}
return object ;
}
}
// ...
}
}
doGetObjectFromFactoryBean() 中,调用到了 getObject(),进入 doGetObjectFromFactoryBean()。
源码中关键代码是这么写的:
1
2
3
4
5
6
7
private Object doGetObjectFromFactoryBean ( final FactoryBean <?> factory , final String beanName ) throws BeanCreationException {
// ...
// 调用FactoryBean的 getObject(),这个方法是实现FactoryBean的类中定义的。
object = factory . getObject ();
// ...
return object ;
}
由此可以看出,在实例化流程 doGetBean() -> getSingleton() -> getObjectForBeanInstance() 中,创建完 bean 实例后,返回的并不一定是 bean 实例本身,如果这个 bean 实现了 FactoryBean 接口,那么最终会返回 getObject() 方法生成的对象,这个对象的创建是实现类自定义的。
技巧
如果一个对象的创建十分复杂,需要设置很多参数、初始化等操作。那么我们可以创建一个FactoryBean实现,专门负责构建这个对象,构建的行为就定义在 getObject() 中。
我们把这个自定义的 FactoryBean 加入到 ioc 容器(在类上添加 @Component 注解等方式),当调用 getBean() 实例化时,最终返回的并非这个 FactoryBean 实现类对象,而是 getObject() 中构建的对象。
4.2 缓存中获取
从上面的代码分析中已经知道,最终调用了 getObject() 之后,会将这个实例缓存到一个变量中,这个变量是 factoryBeanObjectCache
。
回到 doGetBean() 中开始的代码块,先从缓存中获取实例,如果获取到了,同样会调用 getObjectForBeanInstance(),判断实例是否是 FactoryBean 类型。
源码如下:
1
2
3
4
5
6
7
Object sharedInstance = getSingleton ( beanName );
if ( sharedInstance != null && args == null ) {
// ...
// 如果bean不是FactoryBean类型或者beanName以&开头,则直接返回。
// 否则将bean强转为FactoryBean类型,并调用getObject()方法返回。
bean = getObjectForBeanInstance ( sharedInstance , name , beanName , null );
}
在 [
06 循环依赖的实现原理 - getSingleton() ] 中有提到,这里可能返回一个bean实例。实际上在 bean 第一次创建后,后面再获取都是从缓存中拿的。拿到了之后,经过一些处理,就返回。这个处理就是判断 FactoryBean 的处理。
从上面源码中可以看到,如果从缓存中获取到,会调用 getObjectForBeanInstance()
。很明显,在第一次创建 bean 实例时,就调用过这个方法,会把创建的结果缓存到 factoryBeanObjectCache 变量中,这里就直接从 factoryBeanObjectCache 变量中获取的实例。
最终,如果这个 bean 是 FactoryBean 类型,会被替换掉。
4.3 获取原始bean
关于获取原始bean的方式,在 beanName 前加一个前缀 &
,就可以获取到原始 bean 实例。
在 getObjectForBeanInstance() 中有这么一段源码:
1
2
3
4
5
6
7
8
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected Object getObjectForBeanInstance ( Object beanInstance , String name , String beanName , @Nullable RootBeanDefinition mbd ) {
// 如果bean不是FactoryBean类型或者beanName以&开头,则直接返回。
if ( ! ( beanInstance instanceof FactoryBean ) || BeanFactoryUtils . isFactoryDereference ( name )) {
return beanInstance ;
}
}
}
看一下 isFactoryDereference() 的源码:
1
2
3
4
5
public abstract class BeanFactoryUtils {
public static boolean isFactoryDereference ( @Nullable String name ) {
return ( name != null && name . startsWith ( BeanFactory . FACTORY_BEAN_PREFIX ));
}
}
可以看到,如果 beanName以 BeanFactory.FACTORY_BEAN_PREFIX 开头,就会返回true。
BeanFactory.FACTORY_BEAN_PREFIX 常量的声明:
1
2
3
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&" ;
}
结合上面的源码,如果 getBean() 时,传入的 beanName 是以 & 开头,走到 getObjectForBeanInstance() 时,就不会执行 FactoryBean 的逻辑,而是直接返回 bean 实例。