前言
上一篇重点介绍了bean定义信息的注册:
【小家Spring】Spring的Bean定义注册中心BeanDefinitionRegistry详解
本文着眼于Spring的Bean中最重要的类型:单例Bean。研究它的注册中心:SingletonBeanRegistry
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
注意:这个和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
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的方式
基本上我们只要能拿到Bean工厂(一般都可以通过注入的方式拿到),就可以调用SingletonBeanRegistry的相关方法对容器内的单例Bean做一些列的操作~~~
总结
仔细想想,为什么这个类DefaultSingletonBeanRegistry要使用三个存储器呢:
singletonObjects:就是直观的存储着 singleton 的
singletonFactories:是存储的制造 singleton 的工厂
earlySingletonObject:这是一个 早期 singletonFactory 制造出来的 singleton 的缓存
这样处理的好处,是解决依赖、循环依赖的问题。