前言
上一篇文章缓存中获取单例bean讲述了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例bean,就需要重新开始加载bean的所有过程了,这篇文章讲述的就是从头开始加载bean的过程中的一个步骤---获取单例。
获取单例
Spring中使用getSingleton的重载方法实现bean的加载过程,在getBean方法源码中体现:
sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } });
来看一下getSingleton方法的源码:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); //全局变量需要同步 synchronized (this.singletonObjects) { //首先检查对应的bean是否被加载过,因为singleton模式其实就是复用以前创建的bean,所以这一步是必须的 Object singletonObject = this.singletonObjects.get(beanName); //如果为空才可以进行singleton的bean初始化 if (singletonObject == null) { //当工厂的单例对象处于销毁状态时,不允许创建单例bean if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while 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 + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { //初始化bean singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. 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; } afterSingletonCreation(beanName); } if (newSingleton) { //加入缓存 addSingleton(beanName, singletonObject); } } return singletonObject; } }
上述代码其实是使用了回调方法,使得程序在单例创建的前后做一些准备及处理操作,而真正的获得单例bean的方法其实并不是在此方法中实现的,其实逻辑是在ObjectFactory类的实例singletonFactory中实现的。上述代码的处理操作包括如下几步:
(1)检查缓存是否已经加载过;
(2)若没有加载,则记录beanName的状态为正在加载状态;
(3)加载单例前记录加载状态;
其中beforeSingletonCreation(beanName),为空实现,里面没有任何逻辑,其实不是,这个方法中做了一个重要的操作:记录加载状态,也就是通过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过程中所记录的各种辅助状态;
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); } }
(7)返回处理结果。
上述代码的处理过程就到这里结束了。
总结:虽然我们已经从外部了解了加载bean的逻辑架构,但我们现在还没有开始对bean加载功能的探索,之前的文章提到过,bean的加载逻辑其实是在传入的ObjectFactory类的参数singletonFactory中定义的,我们反推参数的获取,得到如下代码:
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>{ public Object getObject() thows BeansWxception{ try { return createBean(beanName, mbd, args); }
} catch (BeansException ex) { destroySingleton(beanName); throw ex; } });
ObjectFactory的核心部分其实只是调用了createBean方法,所以接下来我们还需要到createBean中去追寻bean的加载过程。
参考:《Spring源码深度解析》 郝佳 编著: