Spring 系列目录(http://www.javashuo.com/article/p-kqecupyl-bm.html)html
在 Spring 中 Bean 有单例和多例之分,只有单例的 bean 才会被 BeanFactory 管理,这个工做就是由 SingletonBeanRegistry 完成的。java
public interface SingletonBeanRegistry { void registerSingleton(String beanName, Object singletonObject); Object getSingleton(String beanName); boolean containsSingleton(String beanName); String[] getSingletonNames(); int getSingletonCount(); // 暴露全部的 singletonObjects 给外部 Object getSingletonMutex(); }
SingletonBeanRegistry 的默认实现为 DefaultSingletonBeanRegistry,主要功能以下:spring
// 1. 建立 bean。先从缓存中获取 bean,allowEarlyReference=true 时会尝试从 singletonFactories 获取提暴露的 bean // 缓存中没有就调用 singletonFactory 方法建立 bean public Object getSingleton(String beanName); protected Object getSingleton(String beanName, boolean allowEarlyReference) public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory); // 2. 销毁 bean。能够销毁所有的 bean,也能够销毁指定的 bean,最终都是调用 destroyBean 完成的。 // 销毁 bean 以前须要先销毁依赖它的全部 bean,再调用 bean.destroy() 销毁本身 public void destroySingletons(); public void destroySingleton(String beanName); protected void destroyBean(String beanName, @Nullable DisposableBean bean);
(1) 与单例对象保存有关的四个集合缓存
咱们先从下面四个和单例有关的集合提及。前三个集合和 bean 的建立有关,其中 singletonObjects 保存已经建立成功的 bean 的集合,singletonFactories 和 earlySingletonObjects 属于中间过程,一旦 bean 建立成功就会删除对应的记录,用于解决 bean 属性注入过程当中的循环依赖的问题。最后一个用来保存当前全部已注册的 bean。app
// 1.1 保存最终建立成功的单例 beanName -> beanInstance private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 1.2 中间变量,beanName -> Objectfactory private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 1.3 中间变量,bean 还在建立的时候就能够获取,用于检测循环引用 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 2. 用来保存当前全部已注册的 bean private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
这里涉及用于存储 bean 的不一样的 Map,可能让人感到崩溃,简单解释以下:ide
singletonObjects
:用于保存 beanName 和建立 bean 实例之间的关系,beanName -> beanInstancesingletonfactories
:用于保存 beanname 和建立 bean 的工厂之间的关系,beanName -> ObjectfactoryearlySingletonObjects
:也是保存 beanName 和建立 bean 实例之间的关系,与 singletonObjects 的不一样之处在于,当一个单例 bean 被放到这里面后,那么当 bean 还在建立过程当中,就能够经过 getBean 方法获取到了,其目的是用来检测循环引用。registeredsingletons
:用来保存当前全部已注册的 bean(2) 与单例对象建立有关的几个属性函数
// 1. 保存正在建立的 bean private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); // 2. 保存已经建立的 bean 集合,这样进行依赖循环检查时 // 若是已经 bean 在 inCreationCheckExclusions 中了,就不用再检查 singletonsCurrentlyInCreation 了 private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); // 3. 保存 bean 建立过程时的异常 private Set<Exception> suppressedExceptions;
(3) 与单例对象销毁有关的四个集合ui
// 1. 一旦调用 destroySingletons() 销毁全部的 bean 时就修改成 true private boolean singletonsCurrentlyInDestruction = false; // 2. 下面四个集合都和 bean 的销毁有关 // 2.1 保存每一个 bean 的 destroy 方法 private final Map<String, Object> disposableBeans = new LinkedHashMap<>(); // 3.1 保存当前 bean 内的全部 bean 信息。containingBean -> containedBean // 当注册 containedBeanMap 的同时也会注册 dependentBeanMap 和 dependenciesForBeanMap private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16); // 3.2 保存依赖这个 bean 的全部 bean 的集合,依赖个人。containedBean -> containingBean // 因此销毁这个 bean 的同时也要销毁依赖它的全部 bean private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); // 3.3 保存当前 bean 依赖的全部 bean 的集合,我依赖的。containingBean -> containedBean // 因此销毁这个 bean 只要清空对应的记录便可,而不会销毁该 bean 依赖的其它 bean 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); if (oldObject != null) { throw new IllegalStateException(); } addSingleton(beanName, singletonObject); } } // 这个方法只有在本类中才调用,bean 属性注入完成,直接添加 singletonObject protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } // AbstractAutowireCapableBeanFactory#doCreateBean 调用。注册 singletonFactory protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
这个没什么可说的,主要是要理清这四个集合的功能。能够看到有两种方法注册单例,这两种状况都会将 bean 注册到 registeredSingletons 中:this
addSingleton(String beanName, Object singletonObject)
将其注册到 singletonObjects 中,这段代码的逻辑见 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法。DefaultSingletonBeanRegistry 不只管理了 bean 的注册,还管理 bean 的生命周期,包括 bean 的建立和销毁。code
Spring 中单例只会被建立一次,后续再获取 bean 直接从单例缓存中获取。
getSingleton(beanName)
直接从缓存中获取 bean,也能够指定是否查找提早暴露的 bean(也就是正在建立的 bean)。allowEarlyReference=true 时会查找正在建立的 bean。getSingleton(beanName, singletonFactory)
方法建立单例 bean。由于建立的时候会存在依赖注入的状况,为了解决可能存在的循环依赖问题,Spring 建立 bean 的原则是不等 bean 建立完成就会将建立 bean 的 ObjectFactory 提前曝光加入到缓存中,这样经过 getSingleton(beanName, true)
就能够在缓存中直接查找到这个 bean 的 ObjectFactory。public Object getSingleton(String beanName) { // 参数 true 设置标识容许时期依赖 return getSingleton(beanName, true); } protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 1. 在已经建立完成的 singletonObjects 集合中查找 Object singletonObject = this.singletonObjects.get(beanName); // 2. 若是这个 bean 正在建立,则继续尝试从 earlySingletonObjects 中查找 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 3. 当某些方法须要提早初始化的时候则会调用 addSingletonFactory 方法 // 将对应的 ObjectFactory 初始化策略存储在 singletonFactories ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 调用预先设定的 getObject 方法 singletonObject = singletonFactory.getObject(); // 记录在缓存中,earlySingletonObjects 与 singletonFactories 互斥 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
这个方法步骤以下:
而对于后续的全部内存操做都只为了循环依赖检测时候使用,也就是在 allowEarlyReference=true 的状况下才会使用。
上面讲解了从缓存中获取单例的过程,那么,若是缓存中不存在已经加载的单例 bean 就须要从头开始 bean 的加载过程了,而 Spring 中使用 getSingleton 的重载方法 getSingleton(beanName, singletonFactory) 实现 bean 的加载过程。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' must not be null"); synchronized (this.singletonObjects) { // 1. 首先检查对应的 bean 是否已经加载过 // 由于 singleton 模式其实就是复用已建立的 bean,因此这一步是必须的 Object singletonObject = this.singletonObjects.get(beanName); // 2. 进行 singleton 的 bean 的初始化 if (singletonObject == null) { // 2.1 容器正在销毁抛出异常 if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName); } // 2.2 将这个 bean 添加到 singletonsCurrentlyInCreation 集合中,这样就能够判断 bean 是否存在建立 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { // 2.3 初始化 bean,委托给 ObjectFactory 完成 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // 2.4 ????????? 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; } // 2.5 从 singletonsCurrentlyInCreation 移除该 bean afterSingletonCreation(beanName); } if (newSingleton) { // 2.6 建立成功,加入缓存 addSingleton(beanName, singletonObject); } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
上述代码中实际上是使用了回调方法,使得程序能够在单例建立的先后作一些准备及处理操做,而真正的获取单例 bean 的方法其实并非在此方法中实现的,其实现逻辑是在 ObjectFactory 类型的实例 singletonFactory 中实现的。而这些准备及处理操做包括以下内容:
(1) 检查缓存是否已经加载过
(2) 若没有加载,则记录 beanName 的正在加载状态。
(3) 加载单例前记录加载状态。可能你会以为 beforeSingletonCreation 方法是个空实现,里面没有任何逻辑,但其实不是,这个函数中作了一个很重要的操做:记录加载状态,也就是经过 this.singletonsCurrentlyInCreation.add(beanName) 将当前正要建立的 bean 记录在缓存中,这样即可以对循环依赖进行检测。
protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
(4) 经过调用参数传入的 ObjectFactory 的个体 Object 方法实例化 bean
(5) 加载单例后的处理方法调用。同步骤 (3) 的记录加载状态类似,当 bean加载结東后须要移除缓存中对该 bean 的正在加载状态的记录。
protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
(6) 将结果记录至缓存并删除加载 bean 过程当中所记录的各类辅助状态。
在建立 bean 的过程当中,不少工做都交给 ObjectFactory 这个工厂类完成,那它究竟是什么呢?
public interface ObjectFactory<T> { T getObject() throws BeansException; }
在方法 getSingleton(beanName, singletonFactory)
和 addSingletonFactory(beanName, singletonFactory)
两种都用到了 ObjectFactory,这两处的 ObjectFactory 功能并非同样的。 前者的 ObjectFactory 是用于建立 bean,属于建立型 ObjectFactory,然后者只是简单的持有 bean,属于引用型 ObjectFactory,保存在 singletonFactories 集合中用于解决循环依赖的问题。
(1) 建立型 ObjectFactory
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); }
(2) 引用型 ObjectFactory
在 createBean 建立 bean 的过程当中,在实例化 bean 后就会将这个 bean 提早暴露出来,这样就能够提早在缓存中拿到正在建立的 bean。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) { // 1. 反射建立 bean BeanWrapper instanceWrapper = null; if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); // 2. 将这个 bean 经过 addSingletonFactory 暴露到缓存中,这样指定 allowEarlyReference=true 就能够提早查找到 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // getEarlyBeanReference 默认直接将这个 bean 返回了 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 3. 以后再进行属性注入和初始化等操做 Object exposedObject = bean; populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); }
bean 进行循环依赖检查与两个集合有关:
inCreationCheckExclusions
若是 bean 建立完成则添加到该集合中,这样若是包含要检查的 bean 就不用再检查 singletonsCurrentlyInCreation 了。singletonsCurrentlyInCreation
bean 建立开始时先添加到这个集合中,建立成功后删除// 若是 inCreation=false 则说明对象已经建立成功,直接添加到 inCreationCheckExclusions 集合中,不然就删除 // 这样在进行循环依赖检查时,当这个集合包含该 bean 时就不用检查 singletonsCurrentlyInCreation public void setCurrentlyInCreation(String beanName, boolean inCreation) { Assert.notNull(beanName, "Bean name must not be null"); if (!inCreation) { this.inCreationCheckExclusions.add(beanName); } else { this.inCreationCheckExclusions.remove(beanName); } } // isCurrentlyInCreation 和 isSingletonCurrentlyInCreation 区别仍是没看明白??? public boolean isCurrentlyInCreation(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName)); } // isActuallyInCreation 方法只有在 isCurrentlyInCreation 中调用,不明白为何还要单独抽出来 protected boolean isActuallyInCreation(String beanName) { return isSingletonCurrentlyInCreation(beanName); } public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); }
bean 建立成功后须要注册 bean 以前的依赖关系,这样销毁时才能将依赖它的 bean 也同时销毁
(1) 注册依赖
// 保存当前 bean 内的全部 bean。containingBeanName -> containedBeanName public void registerContainedBean(String containedBeanName, String containingBeanName) { synchronized (this.containedBeanMap) { Set<String> containedBeans = this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8)); if (!containedBeans.add(containedBeanName)) { return; } } registerDependentBean(containedBeanName, containingBeanName); } // dependentBeans 保存依赖个人全部 bean。containedBeanName -> containingBeanName // dependenciesForBeanMap 保存我依赖的全部 bean。containingBeanName -> containedBeanName public void registerDependentBean(String beanName, String dependentBeanName) { // 查找 bean 的注册名称 String canonicalName = canonicalName(beanName); synchronized (this.dependentBeanMap) { // jdk8 若是 key 不存在设置 value,不然返回 oldValue Set<String> dependentBeans = this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8)); // 若是已经注册直接返回 if (!dependentBeans.add(dependentBeanName)) { return; } } synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8)); dependenciesForBean.add(canonicalName); } }
固然若是这个 bean 有销毁方法,也会注册其 DisposableBean
public void registerDisposableBean(String beanName, DisposableBean bean) { synchronized (this.disposableBeans) { this.disposableBeans.put(beanName, bean); } }
(2) 依赖查找
isDependent
查找两个 bean 的依赖关系getDependentBeans
查找依赖这个 bean 的全部 beangetDependenciesForBean
查找这个 bean 依赖的全部 beanisDependent 查找两个 bean 的依赖关系。若是 dependentBeanName 依赖 beanName 则返回 true,这其中会存在间接依赖的状况,如 beanA -> beanB -> beanC,查询 beanA -> beanC 的关系。
protected boolean isDependent(String beanName, String dependentBeanName) { synchronized (this.dependentBeanMap) { return isDependent(beanName, dependentBeanName, null); } } private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) { // 1. alreadySeen 是已经查找过的 bean,这里面的 bean 都不存在依赖关系,若是存在则已经返回 true 了 if (alreadySeen != null && alreadySeen.contains(beanName)) { return false; } // 2. 获取 bean 的注册名称 String canonicalName = canonicalName(beanName); // 3. 查找依赖 beanName 的全部 bean,若是有则确定有依赖,不然还要查找间接依赖 Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { return false; } if (dependentBeans.contains(dependentBeanName)) { return true; } // 4. 逐个查找间接依赖 for (String transitiveDependency : dependentBeans) { if (alreadySeen == null) { alreadySeen = new HashSet<>(); } alreadySeen.add(beanName); if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { return true; } } return false; }
// 销毁全部 bean public void destroySingletons() { synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; } String[] disposableBeanNames; synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { destroySingleton(disposableBeanNames[i]); } this.containedBeanMap.clear(); this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); clearSingletonCache(); } // 销毁指定的 bean public void destroySingleton(String beanName) { removeSingleton(beanName); DisposableBean disposableBean; synchronized (this.disposableBeans) { disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); } destroyBean(beanName, disposableBean); }
真正的销毁在 destroyBean 中完成。
protected void destroyBean(String beanName, @Nullable DisposableBean bean) { // 1. 首先将依赖这个 beanName 的所有销毁 Set<String> dependencies; // ConcurrentHashMap 为何还须要同步??? synchronized (this.dependentBeanMap) { dependencies = this.dependentBeanMap.remove(beanName); } if (dependencies != null) { for (String dependentBeanName : dependencies) { destroySingleton(dependentBeanName); } } // 2. 真正销毁该 beanName if (bean != null) { bean.destroy(); } // 3. 销毁 containedBeans Set<String> containedBeans; synchronized (this.containedBeanMap) { containedBeans = this.containedBeanMap.remove(beanName); } if (containedBeans != null) { for (String containedBeanName : containedBeans) { destroySingleton(containedBeanName); } } // 4. 清理 dependentBeanMap 中残存的 beanName 记录 synchronized (this.dependentBeanMap) { for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) { Map.Entry<String, Set<String>> entry = it.next(); Set<String> dependenciesToClean = entry.getValue(); dependenciesToClean.remove(beanName); if (dependenciesToClean.isEmpty()) { it.remove(); } } } // 5. 清理 dependenciesForBeanMap this.dependenciesForBeanMap.remove(beanName); }
天天用心记录一点点。内容也许不重要,但习惯很重要!