一、介绍
从spring容器中获取单例时有两种情况:缓存中存在和缓存中不存在。缓存中不存在的情况,需要调用getSingleton()方法来获取单例。本章主要介绍获取单例的整体流程,该逻辑中创建bean的步骤较为复杂,放在后面章节单独介绍。
二、bean加载流程
- 获取用户传入name对应的beanName
- 尝试从缓存中获取bean实例
- 缓存中不存在,加载bean实例
3.1. 检查循环依赖
3.2 处理parentBeanFactory
3.3 处理依赖的bean(dependsOn)
3.4 三种bean实例的创建
3.4.1 单例bean的创建
3.4.1.1 获取单例bean,getSingleton()方法(本章解析)
3.4.1.2 创建bean,createBean()方法
3.4.2 原型bean的创建
3.4.3 根据scope策略创建bean - 从bean实例中获取真正的对象
- 转换对象类型
- 返回对象实例
三、相关类及方法
- org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean:加载一个Bean的整体过程都在这个方法中
- org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>):获取单例
- org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingleton:把单例bean存入缓存
四、源码分析
1. 先看加载bean的方法,AbstractBeanFactory#doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1.转换beanName,主要处理别名、以&开头的name
final String beanName = transformedBeanName(name);
Object bean;
// 2.尝试从单例缓存中获取bean实例
Object sharedInstance = getSingleton(beanName);
// 3. 获取bean实例
// 3.1 缓存中已存在bean实例
if (sharedInstance != null && args == null) {
// 省略日志输出代码...
// 从bean实例中获取对象(本章重点,获取实例中的对象)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 缓存中不存在bean实例的情况
else {
// 省略父工厂处理相关代码...
try {
// 省略dependsOn相关代码...
// 3.2 创建单例bean
if (mbd.isSingleton()) {
// 获取单例(本章重点)
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 3.3 创建原型bean实例
else if (mbd.isPrototype()) {
// 省略原型bean创建逻辑...
}
// 3.4 根据scope创建bean实例
else {
// 省略根据scope策略创建bean逻辑...
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 省略其他代码.
...
}
可以看到缓存中不存在bean实例时,创建单例bean的逻辑是调用getSingleton()方法完成的,跟进去看下具体逻辑。
2. 获取单例的整体逻辑
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 同步代码块
synchronized (this.singletonObjects) {
// 1. 再次尝试从缓存中获取bean实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
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 + "'");
}
// 2. 创建单例的前置处理,把该beanName置为创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 3. 通过入参ObjectFactory创建bean(该方法逻辑较为复杂,后面章节单独讲述)
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
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;
}
// 4. 创建单例的后置处理
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 5. 把创建的单例加入到缓存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
3. 创建单例的前置处理
// 保存正在创建中状态的beanName
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
把该beanName加入到DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation,表明该bean正在创建中。
4. 把创建好的单例加入到缓存
// 单例对象缓存: bean name --> bean instance
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 按注册顺序排列的bean名称列表
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 缓存单例对象
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
// 记录已注册beanName
this.registeredSingletons.add(beanName);
}
}
5. 创建单例的后置处理
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
把该beanName从DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation中移除,表明该bean已创建完成。
五、总结
- 从源码分析中看到,容器中已加载的单例bean对象和已注册的beanName保存在DefaultSingletonBeanRegistry类中
// bean对象缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 已注册beanName
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
- 获取单例逻辑可以总结为以下五个步骤
- 再次尝试从缓存中获取bean实例
- 创建单例的前置处理
- 通过入参ObjectFactory创建bean
- 创建单例的后置处理
- 把创建的单例加入到缓存
后面我们就单独讲下第3个步骤:通过入参ObjectFactory创建bean