1、创建BeanWrapper实例

bean对象实例化的第一步:创建BeanWrapper实例:

1
2
3
4
5
6
7
8
9
10
11
// 实例化bean。BeanWrapper:Spring底层javabean基础设施的中心接口。
BeanWrapper instanceWrapper = null;
//如果是单例模式
if (mbd.isSingleton()) {
//未完成的FactoryBean实例缓存中删除beanName
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//使用适当的实例化策略为指定的bean创建一个新实例:工厂方法、构造函数自动装配或简单实例化。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}

BeanWrapper是Spring底层的核心接口,提供分析和操作标准javabean的操作:
获取和设置属性值(单独或批量)、获取属性描述符以及查询属性的可读性/可写性的能力。

首先,如果是单例模式的话,从缓存中获取instanceWrapper,
如果没有获取到,则通过工厂方法、构造函数自动装配或简单实例化策略来创建instanceWrapper。

1.1、createBeanInstance(beanName, mbd, args)

使用适当的实例化策略为指定的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
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
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 确保此时bean类已经被解析。
Class<?> beanClass = resolveBeanClass(mbd, beanName);

//检测beanClass是不是公共的,是否允许非公共访问
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}

//返回一个回调函数,用于创建bean的实例(如果有的话)。
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
//从给定的Supplier获取bean实例。
return obtainFromSupplier(instanceSupplier, beanName);
}

//返回工厂方法(如果有的话)。
if (mbd.getFactoryMethodName() != null) {
//使用命名的工厂方法实例化bean
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// 重新创建同一个bean时的快捷方式…
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
// 四个构造函数字段的公共锁。
synchronized (mbd.constructorArgumentLock) {
//包可见字段,用于缓存已解析的构造函数或工厂方法。
// 如果已缓存的解析的构造函数或者工厂方法不为空,则可以利用构造函数解析
// 因为需要根据参数确认到底使用哪个构造函数,该过程比较消耗性能,所有采用缓存机制
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
//包可见字段,该字段将构造函数参数标记为已解析。
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 已经解析好了,直接注入即可
if (resolved) {
// 自动注入,调用构造函数自动注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
} else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}

// 自动装配的候选构造函数?
// 确定解析的构造函数
// 主要是检查已经注册的 SmartInstantiationAwareBeanPostProcessor
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// 默认构造的首选构造函数?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// 不需要特殊处理:只需使用No -arg构造函数。
return instantiateBean(beanName, mbd);
}

主要的逻辑为:

  • 如果存在Supplie 回调,则调用obtainFromSupplier()获取bean实例。
  • 如果存在工厂方法,则使用工厂方法获取bean实例。
  • 首先判断缓存,如果缓存中存在,即已经解析过了,则直接使用已经解析的。根据 constructorArgumentsResolved 参数来判断是使用构造函数自动注入还是默认构造函数。
  • 如果缓存中没有,则需要先确定到底使用哪个构造函数来完成解析工作,
    因为一个类有多个构造函数,每个构造函数都有不同的构造参数,所以需要根据参数来锁定构造函数并完成初始化,如果存在参数则使用相应的带有参数的构造函数,否则使用默认构造函数。

即有四种获取bean实例的方法:

  1. obtainFromSupplier
  2. instantiateUsingFactoryMethod
  3. autowireConstructor
  4. instantiateBean

后面的文章分析这四种获取bean的实例方法。

tencent.jpg