上一篇重点介绍了bean定义信息的注册:
【小家Spring】Spring的Bean定义注册中心BeanDefinitionRegistry详解
本文着眼于Spring的Bean中最重要的类型:单例Bean。研究它的注册中心:SingletonBeanRegistry
此接口是针对Spring中的单例Bean设计的。提供了统一访问单例Bean的功能。比如我们熟悉的接口ConfigurableBeanFactory
就继承了此接口
ConfigurableListableBeanFactory
是它的子接口,DefaultListableBeanFactory
是它的实现类。 AbstractBeanFactory、AbstractAutowireCapableBeanFactory也是ConfigurableListableBeanFactory的子接口 基本上可以说除了HierarchicalBeanFactory
没有继承此接口,其余的都有直接或间接的实现
我们能够发现,最终真正实现这个接口的,都是BeanFactory
// @since 2.0 Spring2之后才出来这个接口
public interface SingletonBeanRegistry {
// 以指定的名字 把Object放进去
// 1、给定的Object必须是被完全初始化了的(比如new出来的)
// 2、此注册接口不会提供任何用以初始化的回调函数(比如:InitializingBean、afterPropertiesSet都是不会执行的)
// 3、如果此接口的实现类是一个BeanFactory,最好最好最好将你的类注册成Bean Definition而不是直接使用对象(这样就可以使你定义的Bean收到initialization和destruction回调)
void registerSingleton(String beanName, Object singletonObject);
// 仅仅返回已经初始化完成的Bean,对于还没有初始化的Bean Definition不予以考虑
// 但是要注意,此方法**并不支持使用别名**对Bean进行查找,如果只有别名的话,要先通过BeanFactory的接口获取到Bean对应的全限定名称(transformedBeanName())
@Nullable
Object getSingleton(String beanName);
// 检查此实例是否包含指定名字的并且!!!已经初始化完成的单例Bean(不支持别名查找)
// BeanFactory#containsBean是containsSingleton(beanName) || containsBeanDefinition(beanName)
boolean containsSingleton(String beanName);
// 返回容器内所有单例类的名字
String[] getSingletonNames();
// 返回容器内注册的单例类数量
int getSingletonCount();
//@since 4.2 mutex:互斥量 互斥体
Object getSingletonMutex();
}
同样的,按照它的继承结构,着重分析几个典型实现。
注意:这个和
DefaultSingletonBeanRegistry
不一样,这个类非常非常的重要,并且做的事情也很多。甚至认为是Spring容器 所谓的容器的核心内容。 他里面有非常多的缓存,需要解决Bean依赖问题、Bean循环引用问题、Bean正在创建中问题。。。
它继承SimpleAliasRegistry
类和实现了SingletonBeanRegistry
接口,因此这个类可以有别名注册的功能和单例bean注册的功能,并且他还支持注册DisposableBean实例;它依赖ObjectFactory接口和DisposableBean接口(关闭注册表时调用到了destroy方法)。
//共享bean实例的通用注册表 实现了SingletonBeanRegistry. 允许注册表中注册的单例应该被所有调用者共享,通过bean名称获得。
// 可以注册bean之间的依赖关系,执行适当的注入、关闭顺序
// 这个类主要用作基类的BeanFactory实现, 提供基本的管理 singleton bean 实例功能
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// ==========它里面维护了非常非常多的Map、List等 这些构成了我们所谓的容器==========
// 很显然:所有的单例bean最终都会到这里来
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//缓存了bean的name 和 ObjectFactory。 因为最终的Bean都是通过ObjectFactory的回调方法来创建的
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 缓存了已经存在单例,用于解决循环依赖的方法 循环依赖
// 是存放singletonFactory 制造出来的 singleton 的缓存早期单例对象缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 已经注册好的单例bean的名称们 和 singletonObjects保持同步
private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
// ===================以上四个缓存是这个类存放单例bean的主要Map ===========================
// 目前正在创建中的单例bean的名称的集合 存着正在初始化的Bean级不要再次发起初始化了 ===注意是正在===
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 直接缓存当前不能加载的bean
// 这个值是留给开发者自己set的,Spring自己不会往里面放值~~~~
private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//存放异常出现的相关的原因的集合
private Set<Exception> suppressedExceptions;
//标志,指示我们目前是否在销毁单例中</span><span>
private boolean singletonsCurrentlyInDestruction = false;
// 一次性Bean 也就是说Bean是DisposableBean接口的实现
// 实现DisposableBean接口的类,在类销毁时,会调用destroy()方法,开发人员可以重新该方法完成自己的工作
// 目前像里添加的只有`AbstractBeanFactory#registerDisposableBeanIfNecessary` 其实还是来自于 doCreateBean方法
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
// 查找依赖的类 我依赖了哪些们
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
//被依赖的bean key为beanName 我被哪些们依赖了
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
// 添加一个单例对象
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
// 此处加锁
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
// 注意:此处是如果此单例bean已经存在了,直接抛出异常~~~~~
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
// 添加进去一个实例,实际上它做了好几步操作呢
// singletonObjects和singletonFactories是对立关系 不会同时存在
protected void addSingleton(String beanName, Object singletonObject) {
// 注意此处继续上锁
synchronized (this.singletonObjects) {
// 添加进map缓存起来
this.singletonObjects.put(beanName, singletonObject);
// 因为已经添加进去了,所以Factories就可议移除了~~~
this.singletonFactories.remove(beanName);
//已经存在单例(循环依赖)也可以移除了~~~
this.earlySingletonObjects.remove(beanName);
// beanName放进单例注册表中
this.registeredSingletons.add(beanName);
}
}
// 注意:它是一个protected方法,并不是接口方法。子类会向这里添加工厂的~~~
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 首先判断一下:这个bean没有被产生才需要添加工厂,否则啥都不做~~~
// 判断singletonObjects内名字为beanName是否被占用,若没有,进行注册操作
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
//已经存在单例(循环依赖)也可以移除了~~~
this.earlySingletonObjects.remove(beanName);
// 注意注意注意:此处beanName也缓存了哦~~~一定要注意
this.registeredSingletons.add(beanName);
}
}
}
// SingletonBeanRegistry接口的getSingleton方法的实现
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// allowEarlyReference:是否要创建早期引用
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先根据这个beanName去查找,找到value值
Object singletonObject = this.singletonObjects.get(beanName);
// 此处:如果此单例不存在,也不要立马就返回null了 还有工作需要处理呢
// 这里的条件是:如果单例不存在,并且并且这个bean正在chuangjianzhong~~~(在这个singletonsCurrentlyInCreation集合了,表示它正在创建中)
// 什么时候放进这个集合表示创建中呢?调用beforeSingletonCreation()方法,因为他是protected方法,所以只允许本类和子类调用~
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 这里再去earlySingletonObjects去看一下,看是否有呢 如果有直接返回即可
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果还未null,并且 并且allowEarlyReference是允许的 也就是说是允许创建一个早期引用的(简单的说就是先可以把引用提供出去,但是并还没有完成真正的初始化~~~~)
// 这里ObjectFactory就发挥很大的作用了~~~
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 若有对应的ObjectFactory 那就可以继续处理
// 备注:singletonFactories这个Map只有调用`addSingletonFactory()`方法的时候才往里添加
// 它是一个protected方法,目前Spring还只有在`AbstractAutowireCapableBeanFactory#doCreateBean`里有过调用
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 注意此处:把生产出来的放进earlySingletonObjects里面去,表示生产出来了一个引用
this.earlySingletonObjects.put(beanName, singletonObject);
// 然后把nFactories可以移除了,因为引用已经产生了~~~
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
// 这个方法蛮重要的。首先它不是接口方法,而是一个单纯的public方法~~~
// 它的调用处只有一个地方:AbstractBeanFactory#doGetBean 在真正 `if (mbd.isSingleton()) { sharedInstance = getSingleton(...) }`
// 它第二个参数传的是ObjectFactory~~~~~~~实现有创建Bean实例的逻辑~~~
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 在锁内工作~~~~
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
// 很显然如果都不为null了,那还做什么呢 直接返回吧
if (singletonObject == null) {
// 如果目前在销毁singellton 那就抛异常呗~~~~
if (this.singletonsCurrentlyInDestruction) {
// 抛异常
}
// 标记这个bean正在被创建~~~~
beforeSingletonCreation(beanName);
boolean newSingleton = false;
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
... // 省略
} finally {
// 释放这个状态 说明这个bean已经创建完成了
afterSingletonCreation(beanName);
}
// 如果是新创建了 这里执行一下添加 缓存起来~~~~
// 如果是旧的 是不用添加的~~~~
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
// 这两个方法 一个在Bean创建开始之前还行。一个在创建完成后执行 finally里执行
// 表示;beforeSingletonCreation()方法用于记录加载的状态 表示该Bean当前正在初始化中~~~
// 调用this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测啦
// afterSingletonCreation显然就是
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
// 直接检查 singleton object 存储器了,其他的存储器不做检查
@Override
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
@Override
public String[] getSingletonNames() {
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
// 这个方法 只是简单的把这个Map返回出去了~~~~~
@Override
public final Object getSingletonMutex() {
return this.singletonObjects;
}
}
getSingleton
的时候,spring的默认实现是,先从 singleton object 的存储器中去寻找,如果找不到,再从 early singleton object 存储器中寻找,再找不到,那就在寻找对应的 singleton factory,造出所需的 singleton object,然后返回
管理bean的依赖问题, 使用如下三个属性进行管理:
Map<String, Set<String>> containedBeanMap // 依赖的bean name为key , 就是依赖类 -> 查找 被依赖的类
Map<String, Set<String>> dependentBeanMap // 依赖的原始bean name为key
Map<String, Set<String>> dependenciesForBeanMap // 被依赖的bean name为key
这就是DefaultSingletonBeanRegistry
,它实现了接口的所有方法。它还有实现很多Bean依赖之间关系的逻辑,此处不展开了~~~
DefaultSingletonBeanRegistry既有管理SingletonBean 的功能,
又提供了别名的功能
。DefaultSingletonBeanRegistry
是一个通用的存储共享bean实例的地方,通过bean的名字获得bean。同时,它也给提供一次性bean
的注册功能
FactoryBeanRegistrySupport是 工厂bean(FactoryBean)
注册的一个超类,它是一个抽象类,内部多了一个成员变量:
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
它负责缓存由工厂bean
产生的单例bean。它还额外增加了一些方法,用于通过 工厂bean获取 工厂bean所创建的对象的一些信息,下面看看源码:
// 可议看到它是一个首相类,并且继承自`DefaultSingletonBeanRegistry `
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
// 获取factoryBean的类型。 它相对于factoryBean.getObjectType()主要是增加了一些安全校验 这里相关源码我都省略了
@Nullable
protected Class<?> getTypeForFactoryBean(final FactoryBean<?> factoryBean) {
return factoryBean.getObjectType();
}
// 直接从缓存中拿 工厂Bean制造出来的对象
@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}
// 核心方法:从工厂Bean里面拿到这个对象~
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 是单例,并且已经存在该beanName了
if (factory.isSingleton() && containsSingleton(beanName)) {
// 仍然采用这把锁 互斥锁
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
// 显然只有factoryBeanObjectCache里不存在此bean,才需要继续去工厂Bean里面找~
if (object == null) {
// 其实就基本相当于 factory.getObject()
object = doGetObjectFromFactoryBean(factory, beanName);
...
this.factoryBeanObjectCache.put(beanName, object);
}
return object;
}
}
...
}
/**
* Post-process the given object that has been obtained from the FactoryBean.
* The resulting object will get exposed for bean references.
* <p>The default implementation simply returns the given object as-is.
* Subclasses may override this, for example, to apply post-processors.
* @param object the object obtained from the FactoryBean.
* @param beanName the name of the bean
* @return the object to expose
* @throws org.springframework.beans.BeansException if any post-processing failed
*/
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
return object;
}
/**
* Overridden to clear the FactoryBean object cache as well.
*/
@Override
protected void removeSingleton(String beanName) {
synchronized (getSingletonMutex()) {
super.removeSingleton(beanName);
this.factoryBeanObjectCache.remove(beanName);
}
}
// 这里复写了父类的方法。注意:调用了super的方法
@Override
protected void clearSingletonCache() {
synchronized (getSingletonMutex()) {
super.clearSingletonCache();
this.factoryBeanObjectCache.clear();
}
}
// 获取安全上下文
protected AccessControlContext getAccessControlContext() {
return AccessController.getContext();
}
}
它有个唯一子类:AbstractBeanFactory
,它可议说是整个BeanFactory实现的大脑。因为AbstractBeanFactory
继承自FactoryBeanRegistrySupport
,所以不仅仅有注册单例Bean的能力,也有注册工厂Bean的能力了。
到后面的抽象子类AbstractAutowireCapableBeanFactory
,再到实现类DefaultListableBeanFactory
就都有这个功能了。
这里面还有一个继承分支:ConfigurableBeanFactory
有直接继承此接口。同时AbstractBeanFactory
和ConfigurableListableBeanFactory
也都继续继承了ConfigurableBeanFactory
。
而对于ConfigurableListableBeanFactory
它只有唯一实现类:DefaultListableBeanFactory
基本上我们只要能拿到Bean工厂(一般都可以通过注入
的方式拿到),就可以调用SingletonBeanRegistry
的相关方法对容器内的单例Bean做一些列的操作~~~
仔细想想,为什么这个类DefaultSingletonBeanRegistry
要使用三个存储器呢:
singletonFactory 制造出来的
singleton 的缓存这样处理的好处,是解决依赖、循环依赖的问题。