本篇文章分析各个作用域的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
//创建bean实例。
//判断scope是不是"singleton",如果scope为空,也走单例模式。
if (mbd.isSingleton()) {
//返回在给定名称下注册的(原始)单例对象,如果还没有注册,则创建并注册一个新的单例对象。
sharedInstance = getSingleton(beanName, () -> {
try {
//为给定的合并bean定义(和参数)创建bean实例。
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 显式地从单例缓存中删除实例: 它可能是在创建过程中急切地放在那里的,以允许循环引用解析。
//还要删除接收到该bean的临时引用的任何bean
destroySingleton(beanName);
throw ex;
}
});
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//判断scope是否为"prototype"
else if (mbd.isPrototype()) {
// 它是一个原型——>创建一个新实例。
Object prototypeInstance = null;
try {
//原型创建之前的回调。
//默认实现将原型注册为当前正在创建的状态。
beforePrototypeCreation(beanName);
//为给定的合并bean定义(和参数)创建bean实例。
prototypeInstance = createBean(beanName, mbd, args);
} finally {
//原型创建后的回调。
//默认实现将原型标记为不在创建中。
afterPrototypeCreation(beanName);
}
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//request/session/globalsession
else {
String scopeName = mbd.getScope();
//获取 scope 缓存
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// scope 缓存中获取对象
Object scopedInstance = scope.get(beanName, () -> {
//原型创建之前的回调。
//默认实现将原型注册为当前正在创建的状态。
beforePrototypeCreation(beanName);
try {
//为给定的合并bean定义(和参数)创建bean实例。
return createBean(beanName, mbd, args);
} finally {
//原型创建后的回调。
//默认实现将原型标记为不在创建中。
afterPrototypeCreation(beanName);
}
});
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
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);
}
}

1、singleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//判断scope是不是"singleton",如果scope为空,也走单例模式。
if (mbd.isSingleton()) {
//返回在给定名称下注册的(原始)单例对象,如果还没有注册,则创建并注册一个新的单例对象。
sharedInstance = getSingleton(beanName, () -> {
try {
//为给定的合并bean定义(和参数)创建bean实例。
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 显式地从单例缓存中删除实例: 它可能是在创建过程中急切地放在那里的,以允许循环引用解析。
//还要删除接收到该bean的临时引用的任何bean
destroySingleton(beanName);
throw ex;
}
});
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

主要分为两步:

  1. 获取原始bean实例
  2. 获取真正的bean对象

1.1、getSingleton

返回在给定名称下注册的(原始)单例对象,如果还没有注册,则创建并注册一个新的单例对象。

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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//单例对象缓存:bean名称--bean实例。
synchronized (this.singletonObjects) {
//尝试着从缓存中获取,如果存在直接返回,不存在则创建一个新的对象
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//标志,指示我们当前是否在destroysingleton中。
//当这个工厂的单例对象被销毁时,不允许创建单例bean(不要在销毁方法实现中向BeanFactory请求bean !)
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//回调单例创建之前,默认实现注册目前在创建单例。
beforeSingletonCreation(beanName);
boolean newSingleton = false;

//被抑制的异常列表,用于关联相关原因。
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//根据工厂获取原始单例
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
// 是否同时隐式地出现了单例对象?如果是,则继续处理它,因为异常指示该状态。
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
//异常上抛
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//创建单例后的回调。
//默认实现将singleton标记为不在创建中。
afterSingletonCreation(beanName);
}
//如果是一个新的单例
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

尝试的从单例缓存中获取单例对象,如果不存在,则通过工厂创建,并注册到单例缓存中,在创建的前后分别有前后置处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void beforeSingletonCreation(String beanName) {
//当前在创建检查中排除的bean名称集合不包含beanName
//beanName加入当前正在创建的bean的名称集合。
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
//移除singletonsCurrentlyInCreation中的beanName
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

注册单例缓存,将给定的单例对象添加到该工厂的单例缓存中。

1
2
3
4
5
6
7
8
9
10
11
12
protected void addSingleton(String beanName, Object singletonObject) {
//单例对象缓存:bean名称--bean实例。
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
//单例工厂的缓存:bean名称---ObjectFactory。
this.singletonFactories.remove(beanName);
//早期单例对象的缓存:bean名称---bean实例。
this.earlySingletonObjects.remove(beanName);
//一组已注册的单例对象名称集合,按注册顺序包含bean名称。
this.registeredSingletons.add(beanName);
}
}

1.2、getObjectForBeanInstance

这个方法在尝试获取单例的时候分析过了,这边就不贴了。

2、prototype

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 它是一个原型——>创建一个新实例。
Object prototypeInstance = null;
try {
//原型创建之前的回调。
//默认实现将原型注册为当前正在创建的状态。
beforePrototypeCreation(beanName);
//为给定的合并bean定义(和参数)创建bean实例。
prototypeInstance = createBean(beanName, mbd, args);
} finally {
//原型创建后的回调。
//默认实现将原型标记为不在创建中。
afterPrototypeCreation(beanName);
}
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

通过createBean获取bean原始实例。
也有前后置处理,注意prototypesCurrentlyInCreation为ThreadLocal。

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
//当前正在创建的bean的名称。
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
//原型创建之前的回调。默认实现将原型注册为当前正在创建的状态。
@SuppressWarnings("unchecked")
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
} else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
} else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
//原型创建后的回调。默认实现将原型标记为不在创建中。
@SuppressWarnings("unchecked")
protected void afterPrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal instanceof String) {
this.prototypesCurrentlyInCreation.remove();
} else if (curVal instanceof Set) {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.remove(beanName);
if (beanNameSet.isEmpty()) {
this.prototypesCurrentlyInCreation.remove();
}
}
}

也含有getObjectForBeanInstance方法,看样子我应该拉出一篇文章专门分析一下。

3、request/session/global session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 String scopeName = mbd.getScope();
//获取 scope 缓存
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
// scope 缓存中获取对象
Object scopedInstance = scope.get(beanName, () -> {
//原型创建之前的回调。
//默认实现将原型注册为当前正在创建的状态。
beforePrototypeCreation(beanName);
try {
//为给定的合并bean定义(和参数)创建bean实例。
return createBean(beanName, mbd, args);
} finally {
//原型创建后的回调。
//默认实现将原型标记为不在创建中。
afterPrototypeCreation(beanName);
}
});
//获取给定bean实例的对象,对于FactoryBean,要么是bean实例本身,要么是它创建的对象。
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

主要分析scope.get()方法,这个Scope接口的抽象类AbstractRequestAttributesScope中实现了get方法,简单看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
// Retrieve object again, registering it for implicit session attribute updates.
// As a bonus, we also allow for potential decoration at the getAttribute level.
Object retrievedObject = attributes.getAttribute(name, getScope());
if (retrievedObject != null) {
// Only proceed with retrieved object if still present (the expected case).
// If it disappeared concurrently, we return our locally created instance.
scopedObject = retrievedObject;
}
}
return scopedObject;
}

就是从RequestAttributes中获取的对象。

大体上分析完了各个scope中的bean加载,最重要的方法createBean(beanName, mbd, args)之后分析,方法getObjectForBeanInstance(scopedInstance, name, beanName, mbd)后期也想再拉出来分析一下。

tencent.jpg