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 实例。