5.4 获取单例
之前我们讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean就需要从头开始bean的加载过程了,而Spring中使用getSingleton的重载方法实现bean的加载过程。
1 public Object getSingleton(String beanName, ObjectFactory singletonFactory) { 2 Assert.notNull(beanName, "'beanName' must not be null"); 3 //全局变量需要同步 4 synchronized (this.singletonObjects) { 5 //首先检查对应的bean是否已经加载过,因为singleton模式其实就是复用以创建的bean,所以这一步是必须的 6 Object singletonObject = this.singletonObjects.get(beanName); 7 //如果为空才可以进行singleto的bean的初始化 8 if (singletonObject == null) { 9 if (this.singletonsCurrentlyInDestruction) { 10 throw new BeanCreationNotAllowedException(beanName, 11 "Singleton bean creation not allowed while the singletons of this factory are in destruction " + 12 "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); 13 } 14 if (logger.isDebugEnabled()) { 15 logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); 16 } 17 beforeSingletonCreation(beanName); 18 boolean recordSuppressedExceptions = (this.suppressedExceptions == null); 19 if (recordSuppressedExceptions) { 20 this.suppressedExceptions = new LinkedHashSet<Exception>(); 21 } 22 try { 23 //初始化bean 24 singletonObject = singletonFactory.getObject(); 25 } 26 catch (BeanCreationException ex) { 27 if (recordSuppressedExceptions) { 28 for (Exception suppressedException : this.suppressedExceptions) { 29 ex.addRelatedCause(suppressedException); 30 } 31 } 32 throw ex; 33 } 34 finally { 35 if (recordSuppressedExceptions) { 36 this.suppressedExceptions = null; 37 } 38 afterSingletonCreation(beanName); 39 } 40 //加入缓存 41 addSingleton(beanName, singletonObject); 42 } 43 return (singletonObject != NULL_OBJECT ? singletonObject : null); 44 } 45 }
上述代码中其实是使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,而真正的获取单例bean的方法其实并不是在此方法中实现的,其实现逻辑是在ObjectFactory类型的实例singletonFactory中实现的。而这些准备及处理操作包括如下内容。
(1)检查缓存是否已经加载过。
(2)若没有加载,则记录beanName的正在加载状态。
(3)加载单例前记录加载状态。
可能你会觉得beforeSingletonCreation方法是个空实现,里面没有任何逻辑,但其实不是,这个函数中做了一个很重要的操作:记录加载状态,也就是通过this.singletonsCurrentlyIn Creation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测。
1 protected void beforeSingletonCreation(String beanName) { 2 if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletons CurrentlyInCreation.add(beanName)) { 3 throw new BeanCurrentlyInCreationException(beanName); 4 } 5 }
(4)通过调用参数传入的ObjectFactory的个体Object方法实例化bean。
(5)加载单例后的处理方法调用。
同步骤(3)的记录加载状态相似,当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录。
1 protected void afterSingletonCreation(String beanName) { 2 if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletons CurrentlyInCreation.remove(beanName)) { 3 throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); 4 } 5 }
(6)将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态。
1 protected void addSingleton(String beanName, Object singletonObject) { 2 synchronized (this.singletonObjects) { 3 this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); 4 this.singletonFactories.remove(beanName); 5 this.earlySingletonObjects.remove(beanName); 6 this.registeredSingletons.add(beanName); 7 } 8 }
(7)返回处理结果。
虽然我们已经从外部了解了加载bean的逻辑架构,但现在我们还并没有开始对bean加载功能的探索,之前提到过,bean的加载逻辑其实是在传入的ObjectFactory类型的参数singletonFactory中定义的,我们反推参数的获取,得到如下代码:
1 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 2 public Object getObject() throws BeansException { 3 try { 4 return createBean(beanName, mbd, args); 5 } 6 catch (BeansException ex) { 7 destroySingleton(beanName); 8 throw ex; 9 } 10 } 11 });
ObjectFactory的核心部分其实只是调用了createBean的方法,所以我们还需要到createBean方法中追寻真理。