二十、创建Bean之主流程

创建Bean之主流程

承接各个scope创建bean,不论那个scope,创建Bean都会以自己的方式执行createBean()方法。

createBean()抽象方法

1
2
3
// AbstractBeanFactory.java

protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException;
  • 该方法定义在 AbstractBeanFactory 中,其含义是根据给定的 BeanDefinitionargs 实例化一个 Bean 对象。
  • 如果该 BeanDefinition 存在父类,则该 BeanDefinition 已经合并了父类的属性。
  • 所有 Bean 实例的创建,都会委托给该方法实现。
  • 该方法接受三个方法参数:
    • beanName :bean 的名字。
    • mbd :已经合并了父类属性的(如果有的话)BeanDefinition 对象。
    • args :用于构造函数或者工厂方法创建 Bean 实例对象的参数。

createBean()默认实现

该抽象方法的默认实现是在类 AbstractAutowireCapableBeanFactory 中实现:

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
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;

// <1> 确保此时的 bean 已经被解析了
// 如果获取的class 属性不为null,则克隆该 BeanDefinition
// 主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinition
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

// <2> 验证和准备覆盖方法
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// <3> 实例化的前置处理
// 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例
// AOP 的功能就是基于这个地方
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

try {
// <4> 创建 Bean 对象
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

过程如下:

  • <1> 处,解析指定 BeanDefinition 的 class 属性。
  • <2> 处,处理 override 属性。
  • <3> 处,实例化的前置处理。
  • <4> 处,创建 Bean 对象。
解析指定 BeanDefinition 的 class 属性
1
2
3
4
5
6
7
// AbstractAutowireCapableBeanFactory.java

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
  • resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class... typesToMatch) 方法,主要是解析 bean definition 的 class 类,并将已经解析的 Class 存储在 bean definition 中以供后面使用。
  • 如果解析的 class 不为空,则会将该 BeanDefinition 进行设置到 mbdToUse 中。这样做的主要目的是,以为动态解析的 class 是无法保存到共享的 BeanDefinition 中。
处理override属性

lookup-methodreplace-method 这两个标签的用法和解析过程之前有分析,这两个配置存放在 BeanDefinition 中的 methodOverrides 属性中。

我们知道在 bean 实例化的过程中如果检测到存在 methodOverrides ,则会动态地位为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理

之后会做具体分析,此处先看 mbdToUse.prepareMethodOverrides();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// AbstractBeanDefinition.java
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exist and determine their overloaded status.
if (hasMethodOverrides()) {
// 循环,执行 prepareMethodOverride,之前版本执行forEach的时候会先synchronized加锁
getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
}
}
public MethodOverrides getMethodOverrides() {
return this.methodOverrides;
}
private MethodOverrides methodOverrides = new MethodOverrides();

// MethodOverrides.java
private final Set<MethodOverride> overrides = new CopyOnWriteArraySet<>();

如果存在 methodOverrides ,则获取所有的 override method ,然后通过迭代的方法一次调用 prepareMethodOverride(MethodOverride mo) 方法:

1
2
3
4
5
6
7
8
9
10
11
12
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
}
else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}
  • 根据方法名称,从 class 中获取该方法名的个数:
    • 如果个数为 0 ,则抛出 BeanDefinitionValidationException 异常。
    • 如果个数为 1 ,则设置该重载方法没有被重载
  • 若一个类中存在多个重载方法,则在方法调用的时候还需要根据参数类型来判断到底重载的是哪个方法。在设置重载的时候其实这里做了一个小小优化,那就是当 count == 1 时,设置 overloaded = false ,这样表示该方法没有重载。这样,在后续调用的时候,便可以直接找到方法而不需要进行方法参数的校验。
实例化的前置处理
1
2
3
4
5
6
7
8
// AbstractBeanDefinition.java
// <3> 实例化的前置处理
// 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例
// AOP 的功能就是基于这个地方
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}

如果代理对象不为空,则直接返回代理对象,这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。

resolveBeforeInstantiation()如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// AbstractAutowireCapableBeanFactory.java

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//前置
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//后置
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()applyBeanPostProcessorsAfterInitialization() 两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。

执行doCreateBean()创建Bean

如果没有代理对象,就只能走常规的路线进行 bean 的创建了,该过程有 doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 方法来实现。

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {

// Instantiate the bean.
// BeanWrapper 是对 Bean 的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装 bean 的属性描述器
BeanWrapper instanceWrapper = null;
// <1> 单例模型,则从未完成的 FactoryBean 缓存中删除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// <2> 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 包装的实例对象
Object bean = instanceWrapper.getWrappedInstance();
// 包装的实例对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
// <3> 判断是否有后置处理
// 如果有后置处理,则允许后置处理修改 BeanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 后置处理修改 BeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// <4> 解决单例模式的循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && // 单例模式
this.allowCircularReferences && // 运行循环依赖
isSingletonCurrentlyInCreation(beanName));// 当前单例 bean 是否正在被创建
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 提前将创建的 bean 实例加入到 singletonFactories 中
// 这里是为了后期避免循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// Initialize the bean instance.
// 开始初始化 bean 实例对象
Object exposedObject = bean;
try {
// <5> 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
// 则会递归初始依赖 bean
populateBean(beanName, mbd, instanceWrapper);
// <6> 调用初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// <7> 循环依赖处理
if (earlySingletonExposure) {
// 获取 earlySingletonReference
Object earlySingletonReference = getSingleton(beanName, false);
// 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
if (earlySingletonReference != null) {
// 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
// 处理依赖
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}

// Register bean as disposable.
// <8> 注册 bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}

整体流程:

  • <1> 处,如果是单例模式,则清除缓存。
  • <2> 处,调用 createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 方法,实例化 bean ,主要是将 BeanDefinition 转换为 org.springframework.beans.BeanWrapper 对象。
  • <3> 处,MergedBeanDefinitionPostProcessor 的应用。
  • <4> 处,单例模式的循环依赖处理。
  • <5> 处,调用 populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) 方法,进行属性填充。将所有属性填充至 bean 的实例中。
  • <6> 处,调用 initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法,初始化 bean 。
  • <7> 处,依赖检查。
  • <8> 处,注册 DisposableBean 。

二十、创建Bean之主流程
http://www.muzili.ren/2022/06/11/创建Bean之主流程/
作者
jievhaha
发布于
2022年6月11日
许可协议