Spring解密 - Bean 加载流程

文章目录
  1. 1. 前言
    1. 1.1. 入口
  2. 2. 解密
  3. 3. BeanFactory 的由来
  4. 4. Bean 加载
    1. 4.1. 转换 BeanName
    2. 4.2. 加载单例
    3. 4.3. 创建 Bean
    4. 4.4. 初始化 Bean
    5. 4.5. 增强的 Bean
    6. 4.6. 循环依赖
  5. 5. 总结
  6. 6. 说点什么

Spring是一个开源的设计层面框架,解决了业务逻辑层和其他各层的松耦合问题,将面向接口的编程思想贯穿整个系统应用,同时它也是Java工作中必备技能之一…

前言

Spring解密 - XML解析 与 Bean注册 中,讲了 Bean的解析,本章将详细讲解Spring中Bean的加载过程,相比解析而言,加载稍微复杂一点.

入口

1
2
3
4
5
6
7
8
9
public class Application {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Person person = context.getBean("person", Person.class);
System.out.println(person.toString());
}
}

重点分析 context.getBean();

解密

在分析 Bean 的加载过程前,我们看看 BeanFactory 的由来,以及 getBean 所属的类是谁。磨刀不误砍柴工

BeanFactory 的由来

1.查看getBean()的源码,此处的 getBeanFactory() 是怎么来的?

1
2
3
4
5
6
7
8
9
public class AbstractApplicationContext{

@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
// getBeanFactory() 是怎么来的?我们接着看
return getBeanFactory().getBean(name, requiredType);
}
}

2.应用程序的上下文

new ClassPathXmlApplicationContext("bean.xml"); 中,跳转到重载的构造方法中,我们会发现如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ClassPathXmlApplicationContext {

public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {

super(parent);
// 解析 bean.xml 文件
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}

}

它的目的是将普通路径解析为 类(classpath) 路径资源名称。多个配置文件的情况下,后加载的 Bean 会覆盖先前定义好的 Bean,这样做的目的是为了通过额外的XML文件来特意重写某个 Bean这里我们可以看到调用了一个 refresh(),它的作用是什么呢?

3.初始化

刷新容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AbstractApplicationContext {

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新上下文
prepareRefresh();
// 通知子类,刷新内部 BeanFactory(创建 BeanFactory 的入口)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
}
}

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 跟踪该方法
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

}

初次加载完 bean.xml 后,肯定会进入到 refresh() 方法中,这个时候会做容器初始化的工作,也就是 标签解析、Bean加载 等等工作,由于本章重点介绍 Bean加载,所以只贴了少量代码(看官莫急)

创建 DefaultListableBeanFactory

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
public class AbstractRefreshableApplicationContext {

@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断是否存在
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 然后赋值给 beanFactory 变量
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

// 提取 BeanFactory
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
}

从上面的代码块中,我们可以看到 如果已经存在 beanFactory,将销毁旧的实例,然后在创建新的 DefaultListableBeanFactory,最后 getBeanFactory() 就可以正常使用了。

Bean 加载

整个 Bean 的装载过程中,重点围绕 AbstractBeanFactory,只要把它搞定剩下的就轻松了

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
public abstract class AbstractBeanFactory {

@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 别名转换
final String beanName = transformedBeanName(name);
Object bean;

// 检查缓存中是否存在 该 Bean 的单例(Bean默认的Scope = singleton)
// 比如容器初始化的时候或者其他地方调用过getBean,已经完成了初始化
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 返回实例,FactoryBean 的情况下,并不是直接返回实例本身而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// 存在循环依赖则报错
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 判断工厂中是否含有当前 Bean 的定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果没有,查询父工厂
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 执行带有 args 参数的 getBean 方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 如果没有参数,执行标准的 getBean 方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

if (!typeCheckOnly) { // 如果不是做类型检查,则需要标记此 Bean 正在创建之中
markBeanAsCreated(beanName);
}

try {
// 将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,如果BeanName是子Bean的话会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// 获取依赖的 Bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
getBean(dep);
}
}

// 终于开始创建 Bean 实例了,如果是单例的,那么会创建一个单例的匿名工厂,
// 如果是原型模式的,则不需要创建单例的工厂的,其他的如 request、session 作用域的,则根据自身的需要
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// 类型检查,如果不能进行类型转换,则抛出异常
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

}

整个代码块的内容还是不少的,接下来我们一步一步的分析。

转换 BeanName

1
2
3
4
5
final String beanName = transformedBeanName(name);

protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

去除 FactoryBean 的修饰符,最终取指定 alias 所表示的 beanName。因为有可能获取到以 & 开头的 FactoryBean,所以要进行转化(关于 BeanFactoryFactoryBean 后面会进行区分)

加载单例

检查缓存中是否存在 该 Bean 的单例(Bean默认的Scope = singleton),如容器初始化的时候或者其他地方已经调用过 getBean() 完成了初始化

1
Object sharedInstance = getSingleton(beanName);

缓存加载 Bean

默认在装载 Bean 的时候会先去检查 singletonObjects 是否存在,如果存在直接提取缓存的。

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
public class DefaultSingletonBeanRegistry {

/** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 保存 BeanName 和创建 bean 实例的工厂之间的关系 bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** 保存 BeanName 和创建 bean 实例之间的关系 bean name --> bean instance */
/** 与 singletonObjects 不同的是当一个单例 bean 被放到里面后,那么在 bean 在创建过程中,就可以通过 getBean 方法获取到,可以用来检测循环引用。 **/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** 保存当前所有已注册的 bean */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 尝试从缓存获取实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 若该 bean 正在加载则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 存入到缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

}

构建实例(无缓存情况)

缓存中没有,那就当场构建一个 bean 出来,可以看到 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 有两个参数,其中的 ObjectFactory 是怎么来的呢? 接着往下看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 记录加载状态,,以便对循环依赖进行检测
beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
// 移除加载状态
afterSingletonCreation(beanName);
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}

构建 ObjectFactory

此处与其说是构建 ObjectFactory ,不如说是在创建一个单例 Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 对 JDK8 lambda 表达式熟悉的小伙伴就不会陌生了
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
// 划重点了
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

创建 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
public class AbstractAutowireCapableBeanFactory {

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

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

// 首先判断需要创建的bean是否可以被实例化,这个类是否可以通过类装载器来载入。
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

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

try {
// 用 BeanPostProcessors 返回代理来替代真正的实例(如果 Bean 配置了 PostProcessor,那么这里返回的是一个代理)
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 {
// 重点来了
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException ex) {
// A previously detected exception with proper bean creation context already...
throw ex;
}
catch (ImplicitlyAppearedSingletonException ex) {
// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}


}

在创建 Bean 之前,Spring 还做了不少工作。

  • 判断创建的 bean 是否可以被实例化,这个类是否可以通过 ClassLoader 来载入,根据设置的 class 属性或根据 className 来解析 class
  • 对覆盖进行标记并验证,在 Spring 配置中存在 lookup-mothodreplace-method 的,这两个配置的加载时将配置统一存放在 BeanDefinition 中的 methodOverrides 属性里,这个方法的操作也是针对于这两个配置的;
  • 应用初始化前的后处理器,最后创建 bean。在 createBean() 方法里执行完 resolveBeforeInstantiation 方法后,如果创建了代理且不为空的话就直接返回,否则需要进行常规 bean 的创建,这个创建过程是在 doCreateBean 中完成的

初始化 Bean

上面 createBean 交给了 doCreateBean 来创建 bean (上面还有一个重要的方法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
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
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {

// 实例化 Bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根据指定 bean 使用相应策略创建实例(正确情况会调用无参构造函数)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取实例化好的 Bean(Person person = new Person()),此处还未进行赋值
final Object bean = instanceWrapper.getWrappedInstance();
// 获得实例化好的 class
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}

// 记录创建 Bean 的 ObjectFactory,初始化前调用 post-processors,可以让我们在 bean 实例化之前做一些定制操作
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}

// 检测循环依赖,是否需要提早初始化(只能解决单例Bean)
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// 初始化bean实例。
Object exposedObject = bean;
try {
// 在这个方法里面初始化对象,配置 xml 中的各种属性
populateBean(beanName, mbd, instanceWrapper);
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);
}
}

if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
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 " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}

// 用于销毁方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}

return exposedObject;
}

上面源码完成的操作可以概括为以下几点

  • RootBeanDefinition 是不是单例,如果是单例先移除缓存
  • 实例化 bean,将 RootBeanDefinition 转换为 BeanWrapper
  • 使用 MergedBeanDefinitionPostProcessorAutowired注解 就是通过此方法实现类型的预解析;
  • 解决循环依赖问题
  • populateBean() 中填充属性,配置在 XML 中的各种属性
  • 注册到 DisposableBean
  • 完成创建并返回 Bean 的实例

接下来我们看下 Spring 是如何创建 bean 实例的。跟踪 createBeanInstance() 方法

创建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
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 获取 beanClass , 要先确保 Bean 是正确的,已经解析到当前节点了
Class<?> beanClass = resolveBeanClass(mbd, beanName);

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());
}

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}

// 若工厂方法不为空则使用工厂方法初始化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// Shortcut when re-creating the same 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);
}
}

// 根据参数解析构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// 没有特殊处理的情况下,只需使用无参数的构造函数。
return instantiateBean(beanName, mbd);
}

可以看出如果在 RootBeanDefinition 中存在 factoryMethodName属性,或者说配置文件中配置了 factory-method,那么 Spring 会尝试使用 instantiateUsingFactoryMethod(beanName, mbd, args) 方法根据 RootBeanDefinition 中的配置生成bean实例。然后再解析构造方法并进行实例化,Spring 会根据参数及类型判断使用哪个构造方法进行实例化。判断调用哪个构造方法的过程会采用缓存机制,如果已经解析过则不需要重复解析而是从 RootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需再次解析。

populateBean 属性注入

这块代码比较多,有兴趣请自行跟进,就不贴出来了

populateBean 方法的中的主要处理流程:

  • InstantiationAwareBeanPostProcessor 处理器的 postProcessAfterInstantiation 方法控制程序是否继续填充属性;
  • 根据注入类型提取依赖的 bean,并存入 PropertyValues 中;
  • InstantiationAwareBeanPostProcessor 处理器的 postProcessPropertyValues 方法对属性在填充前再次处理(主要还是验证属性);
  • 将所有 PropertyValues 中的属性填充到 BeanWrapper 中;

initializeBean 初始化Bean

学过 Spring 的都知道 bean 配置时有一个 init-method 属性,这个属性的作用是在 bean 实例化前调用 init-method 指定的方法进行需要的操作,现在就进入这个方法了;Spring 执行过 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
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 特殊bean处理
invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
// 调用配置的 init-method
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

最后加载完 Bean 并执行完初始化操作后,一个 bean 的加载基本就结束了。

增强的 Bean

通过上面的描述,我们已经知道了一个的 Bean 是如何初始化的,已经具备普通 Bean 的功能。但是 Spring 还提供了一种增强的 Bean(FactoryBean),具备 factory 能力的 Bean,这个能力主要在 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
public class AbstractBeanFactory {

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

// 如果想要获取 FactoryBean 本身,那么 beanInstance 必须是 FactoryBean 的实例
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}

// 如果 instance 不是 FactoryBean 实例,或者想要获取的就是 FactoryBean 实例,那么直接返回就好
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}

Object object = null;
if (mbd == null) {
// 获取缓存的实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 缓存中没有对象,那么从头准备 bean defition 实例化一个
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());
// 在这里面获得最终的FactoryBean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

}

关于 BeanFactoryFactoryBean 的区别:

  • BeanFactory: 容器的基本接口,是一个工厂,用来生产 Bean
  • FactoryBean: 是一个特殊的 Bean,可以当作工厂使用的 Bean

循环依赖

上面有简单提到过 循环依赖(只有在单例情况下才会尝试解决循环依赖)。 无法解决就只能抛出 BeanCurrentlyInCreationException 异常

构造器循环依赖

无法解决,只能抛出 BeanCurrentlyInCreationException 异常

1
2
3
4
5
6
7
8
9
<bean id="A" class="com.battcn.A">
<constructor-arg index="0" ref="B" />
</bean>
<bean id="B" class="com.battcn.B">
<constructor-arg index="0" ref="C" />
</bean>
<bean id="C" class="com.battcn.C">
<constructor-arg index="0" ref="A" />
</bean>

setter 循环依赖

Spring 容器提前暴露了刚好完成的构造器注入,但未完成其他步骤 (如 setter 注入bean)。只能解决单例作用域的 bean 循环依赖。

1
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

prototype 范围的依赖处理

Spring 容器无法完成依赖注入,因为 Spring 容器不会缓存 prototype 作用域的 bean,因此无法提前暴露一个创建中的 bean

1
2
3
4
5
6
7
8
9
<bean id="A" class="com.battcn.A" scope="prototype">
<property name="B" ref="B" />
</bean>
<bean id="B" class="com.battcn.B" scope="prototype">
<property name="C" ref="C" />
</bean>
<bean id="C" class="com.battcn.C" scope="prototype">
<property name="A" ref="A" />
</bean>

总结

熬过几个无人知晓的秋冬春夏,撑过去一切都会顺着你想要的方向走…

说点什么

全文代码:https://gitee.com/battcn/battcn-spring-source/tree/master/Chapter4

  • 个人QQ:1837307557
  • battcn开源群(适合新手):391619659

微信公众号:battcn(欢迎调戏)

分享到