获取单例bean getSingleton

明明之前一篇已经讲过了获取单例,为什么这里又是获取单例bean呢?

两天不看书,果断又忘了.前面学的是从缓存中获取,这里是真正的获取.

DefaultSingletonBeanRegistry 中重载此方法,第二参数为ObjectFactory<?>

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
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
//这里再次看到了这个singletonObjects,上篇文章介绍过,是维护了单例对象
//书中说法是:用于保存BeanName和创建bean实例之间的关系
Map var3 = this.singletonObjects;
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
//首先获取一遍,如果不存在,才去创建
if (singletonObject == null) {
//工厂如果正在销毁,这时候获取bean就会报错
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
}

if (this.logger.isDebugEnabled()) {
//打印日志,正在创建单例bean(beanName)的共享的实例
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//标志这个beanName正在创建,如果同时重复创建,会报错
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}

try {
//=============这里应该是最关键的创建bean的步骤===============
singletonObject = singletonFactory.getObject();
//标识新创建出来的单例
newSingleton = true;
} catch (IllegalStateException var16) {
//非法状态错误,应该是创建过程中发现存在其他线程已创建此单例
//所以此处catch里面再次调用了singletonObjects.get(beanName);
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
//其它创建bean错误
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
//把其它recordSuppressedExceptions塞入这个ex一并抛出
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//确认这个beanName在几个set中的状态
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
//如果是新创建的,则加入缓存,移除几个新创建的标识,名字加入registeredSingletons
this.addSingleton(beanName, singletonObject);
}
}
//返回,如果是NULL_OBJECT也作为null返回.
//这个NULL_OBJECT应该是在前面的获取方法中有可能的特殊返回值
return singletonObject != NULL_OBJECT ? singletonObject : null;
}
}

从上可以看出,获取单例还是通过 synchronized(this.singletonObjects) 加锁来实现,先从 singletonObjects 查一遍有没有已存在的,若没有则再进行创建。

而创建的步骤,则是在入参的 ObjectFactory<?> 中完成,调用其 getObject() 依然还是调用我们本身AbstractBeanFactorycreateBean 方法。


我们先不急着往下看,先理一理,首先第一点要知道的是单例加锁都是 synchronized(this.singletonObjects) 。其次获取单例 bean 的大致步骤,无非就是:

  1. 上一文中介绍的,从缓存中拿,并且允许“早期引用” ,即从 earlySingletonObjects 中拿。

  2. 如果缓存中没有,则自己创建,

    2.1 在各种 map 里记录它的 创建、销毁等信息

    2.2 通过createBean 方法去具体创建这个实例。