5.4 获取单例
之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean就需要从头开始bean的加载过程了,而Spring中使用getSingleton的重载方法实现bean的加载过程。
DefaultSingletonBeanRegistry.java
/** * Return the (raw) singleton object registered under the given name, creating and * registering a new one if none registered yet. * * @param beanName the name of the bean * @param singletonFactory the ObjectFactory to lazily create the singleton with, if * necessary * @return the registered singleton object */ public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' must not be null"); // 全局变量需要同步 synchronized (this.singletonObjects) { // 首先检查对应的bean是否已经加载过,因为singleton模式其实就是复用以创建的bean,所以这一步是必须的 Object singletonObject = this.singletonObjects.get(beanName); // 如果为空才可以进行singleto的bean的初始化 if (singletonObject == null) { 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 (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } // 记录加载状态,也就是通过this.singletonsCurrentlyIn // Creation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测。 beforeSingletonCreation(beanName); boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { // 初始化bean singletonObject = singletonFactory.getObject(); } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } // 同 beforeSingletonCreation // 的记录加载状态相似,当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录。 afterSingletonCreation(beanName); } // 将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态。 addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
上述代码中其实是使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,而真正的获取单例bean的方法其实并不是在此方法中实现的,其实现逻辑是在ObjectFactory类型的实例singletonFactory中实现的。而这些准备及处理操作包括如下内容。
(1)检查缓存是否已经加载过。
(2)若没有加载,则记录beanName的正在加载状态。
(3)加载单例前记录加载状态。
可能你会觉得beforeSingletonCreation方法是个空实现,里面没有任何逻辑,但其实不是,这个函数中做了一个很重要的操作:记录加载状态,也就是通过this.singletonsCurrentlyIn Creation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测。
/** * Callback before singleton creation. * <p> * The default implementation register the singleton as currently in creation. * * @param beanName the name of the singleton about to be created * @see #isSingletonCurrentlyInCreation */ // 记录加载状态,也就是通过this.singletonsCurrentlyIn // Creation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测。 protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } }
(4)通过调用参数传入的ObjectFactory的getObject方法实例化bean。
(5)加载单例后的处理方法调用。
同步骤(3)的记录加载状态相似,当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录。
/** * Callback after singleton creation. * <p> * The default implementation marks the singleton as not in creation anymore. * * @param beanName the name of the singleton that has been created * @see #isSingletonCurrentlyInCreation */ // 同 beforeSingletonCreation // 的记录加载状态相似,当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过程中所记录的各种辅助状态。
/** * Add the given singleton object to the singleton cache of this factory. * <p> * To be called for eager registration of singletons. * * @param beanName the name of the bean * @param singletonObject the singleton object */ // 将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态。 protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
(7)返回处理结果。
虽然我们已经从外部了解了加载bean的逻辑架构,但现在我们还并没有开始对bean加载功能的探索,之前提到过,bean的加载逻辑其实是在传入的ObjectFactory类型的参数singletonFactory中定义的,我们反推参数的获取,得到如下代码:
/** * Add the given singleton factory for building the specified singleton if necessary. * <p> * To be called for eager registration of singletons, e.g. to be able to resolve * circular references. * * @param beanName the name of the bean * @param singletonFactory the factory for the singleton object */ protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
AbstractBeanFactory.doGetBean
// 实例化依赖的bean后便可以实例化mbd本身了 // Create bean instance. if (mbd.isSingleton()) {// singleton模式的创建 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It // might have been put there // eagerly by the creation process, to allow for circular // reference resolution. // Also remove any beans that received a temporary // reference to the bean. destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
ObjectFactory的核心部分其实只是调用了createBean的方法,所以我们还需要到createBean方法中追寻真理。