从源码认识FactoryBean

本文学习自马士兵MAC课程-源码五班

目的

通过 Debug 探究以下问题:

  1. AbstractApplicationContextrefresh() 中,完成对 bean 的实例化方法 finishBeanFactoryInitialization(beanFactory) 是否会实例化 UserFactoryBean 和 User 的对象
  2. context.getBean(“&userFactoryBean”)context.getBean(“userFactoryBean”) 会返回不同对象的逻辑是什么?

案例代码

User

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.eitan.factorybean.entity;

public class User {
private String username;

public String password;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

BeanFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.eitan.factorybean.factorybean;

import com.eitan.factorybean.entity.User;
import org.springframework.beans.factory.FactoryBean;

public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
return user;
}

@Override
public Class<?> getObjectType() {
return User.class;
}

@Override
public boolean isSingleton() {
return true;
}
}

factorybean.xml

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userFactoryBean" class="com.eitan.factorybean.factorybean.UserFactoryBean"></bean>
</beans>

ApplicationContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.eitan.factorybean;

import com.eitan.factorybean.entity.User;
import com.eitan.factorybean.factorybean.UserFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyApplicationContext {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("factorybean.xml");
UserFactoryBean userFactoryBean = (UserFactoryBean) context.getBean("&userFactoryBean");
System.out.println(userFactoryBean);
User user = (User) context.getBean("userFactoryBean");
System.out.println(user);
}
}

这里我们手动获取了 UserFactoryBean 和 User,通过 Debug 跟踪其获取的具体步骤

首先关注 finishBeanFactoryInitialization(beanFactory) 方法

finishBeanFactoryInitialization(beanFactory)

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
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 为上下文初始化类型转换器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果beanFactory之前没有注册前入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}

// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 尽早初始化loadTimeWeaverAware,以便尽早注册它们的转换器
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

// Stop using the temporary ClassLoader for type matching.
// 禁止使用临时类加载器进行类型匹配
beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步处理
beanFactory.freezeConfiguration();

// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的单例对象
beanFactory.preInstantiateSingletons();
}

这个方法主要还是做了一些初始化前的准备操作,具体初始化发生在 beanFactory.preInstantiateSingletons()

preInstantiateSingletons()

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}

// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 将所有BeanDefinitionNames创建一个集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载的单例bean的初始化,遍历集合的对象
for (String beanName : beanNames) {
// 合并父类BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 条件判断,非抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否实现了FactoryBean接口
if (isFactoryBean(beanName)) {
// 根据&+beanName来获取具体对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 进行类型转换
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
// 判断这个FactoryBean是否希望急切的初始化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
// 如果希望急切的初始化,则通过beanName获取bean实例
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
getBean(beanName);
}
}
}

// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}

beanDefinitionNames

这里的 beanDefinitionNames 是包括所有通过 xml 配置和注解扫描到(这个案例没有开启注解扫描)的 BeanDefinitionName,本案例只包含一个在 xml 中配置的 userFactoryBean

image-20210812235437097

getMergedLocalBeanDefinition(beanName)

1
2
3
4
5
6
7
8
9
10
11
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 检查beanName对应的mergedBeanDefinitions是否存在于缓存中,此缓存是在beanFactoryPostProcessor中添加的
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
// 如果存在于缓存中则直接返回
return mbd;
}
// 如果不存在于缓存中,根据beanName和BeanDefinition,获取mergedBeanDefinitions
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

getMergedLocalBeanDefinition(beanName) 的用途是根据 beanName 获取对应的 BeanDefinition,这里返回的是已经与 parentBeanDefinition 合并后的 BeanDefinition

  1. 通过 Debug 得知,此时是直接从缓存 mergedBeanDefinitions 中获取到 BeanDefinition 直接放回,那么它是合适首次进行合并操作并加入缓存的呢?是在调用 BeanFactoryPostProcessor 时 beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false) 方法中首次进行 merge 操作的。
  2. 该方法返回的 BeanDefinition 为 RootBeanDefinition。Spring 通过 xml 配置的 BeanDefinition 为 GenericBeanDefinition,而通过注解扫描 doScan() 找到的为 ScannedGenericBeanDefinition,通过该方法会将其同一转成 RootBeanDefinition
  3. 合并父类BeanDefinition的逻辑为:
    1. 先判断该BeanDefinition有无父类,如果没有则直接转化为 RootBeanDefinition 返回
    2. 如果有父类,则递归调用 getMergedBeanDefinition(String name) 方法得到父类的 BeanDefinition,并将父类合并子类,最终返回合并后的 BeanDefinition

isFactoryBean(beanName)

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
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
// 拿到真正的beanName
String beanName = transformedBeanName(name);
// 尝试从缓存中获取bean实例对象
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
// 如果beanInstance存在,则直接判断类型是否为FactoryBean
return (beanInstance instanceof FactoryBean);
}
// No singleton instance found -> check bean definition.
// 如果缓存中不存在此 beanName && 父beanFactory是ConfigurableBeanFactory,则调用父BeanFactory判断是否为FactoryBean
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
// 通过MergedBeanDefinition来检查beanName对应的bean是否为FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}




protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
// 获取RootBeanDefinition的isFactoryBean属性
Boolean result = mbd.isFactoryBean;
// 如果结果为空
if (result == null) {
// 拿到beanName对应的bean实例的类型
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
// 返回beanType是否为factoryBean本身、子类或子接口
result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
mbd.isFactoryBean = result;
}
return result;
}

可以看到该方法一开始就使用 String beanName = transformedBeanName(name) 去除 & 符号,因此不管入参是否带 & 都是判断同一个 beanName 是否为工厂类

之后的操作就是 getBean、doGetBean、createBean 和 doCreateBean,这不在我们此次探究范围之内暂且跳过,只要明白在 refresh 方法执行后:

  1. BeanFactorybeanDefinitionMap 中只有一对键值对,key = userFactoryBean,value 为 UserFactoryBean 对应的 BeanDefinition

image-20210813002902145

  1. 在 BeanFactory 的 singletonObjects 中,存在一个键值对,key = userFactoryBean,value 为类型 是 UserFactoeyBean 的对象

image-20210813003703270

getBean(String name)

在完成了 ApplicationContext 的创建之后,当我们手动调用 context.getBean(“&userFactoryBean”) 和 *context.getBean(“userFactoryBean”)*,Spring 内部是如何处理的呢?

doGetBean(…)

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
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

// 提取对应的beanName,当bean对象实现FactoryBean接口之后就会变成&beanName
// 这一步的操作是去除&符号
String beanName = transformedBeanName(name);
Object beanInstance;

// Eagerly check singleton cache for manually registered singletons.
// 提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联
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 + "'");
}
}
// 返回对象的实例,当你实现Factory接口,需要获取具体的对象就需要此方法进行获取
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 当从 singletonObjects 缓存中获取不到时,走的是 createBean 创建流程
else {
...
}

return adaptBeanInstance(name, beanInstance, requiredType);
}
  1. String beanName = transformedBeanName(name) 的作用是会将 & 符号去除,因此无论入参 name 为 &userFactoryBean 还是 userFactoryBean,得到的beanName 均为 userFactoryBean
  2. 由上文可知,此时在 singletonObjects 中是存在了 “userFactoryBean” -> UserFactoryBean 的对象 的缓存,因此这里的 Object sharedInstance = getSingleton(beanName) 返回的就是一个 UserFactoryBean 的对象
  3. 最终返回的对象是由 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null) 方法得到的,这里会把 namebeanName 都当作参数传入

getObjectForBeanInstance(…)

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
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.
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;
}

// 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.
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}

Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
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());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
  1. BeanFactoryUtils.isFactoryDereference(name) 方法,通过是否是 & 开头来判断返回结果是工厂还是工厂创建的实体类
  2. 如果 name 是 & 开头,代表需要返回的就是工厂本身,则直接把入参的 beanInstance 返回即可
  3. 如果是返回工厂创建的实体类:
    1. 先从缓存 factoryBeanObjectCache 中去寻找,如果缓存中有则直接返回
    2. 缓存中没有则通过 getObjectFromFactoryBean(factory, beanName, !synthetic) 创建

getObjectFromFactoryBean(factory, beanName, !synthetic)

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
45
46
47
48
49
50
51
52
53
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 如果工厂创建的类是单例的,并且一级缓存中已经存在这个工厂,则先尝试从缓存中获取
// 否则直接使用工厂创建一个新的bean并返回
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
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 的 isSingleton() 方法是如何生效的

  1. 在方法最开始时就会调用 isSingleton() 进行判断,如果是单例的会先从缓存 factoryBeanObjectCache 中获取,获取不到再进行创建
  2. 如果不是 singleton,则直接调用 doGetObjectFromFactoryBean(factory, beanName)
  3. 获取到对象之后,调用 this.factoryBeanObjectCache.put(beanName, object) 将其放入缓存

doGetObjectFromFactoryBean(factory, beanName)

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
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() 方法
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() 方法来获取对应对象

总结

image-20210813100555949