spring IOC:DefaultSingletonBeanRegistry

来源:互联网 发布:在线写js 编辑:程序博客网 时间:2024/06/13 04:22

 

 

spring IOC:DefaultSingletonBeanRegistry

http://whoknow.javaeye.com/blog/487786

假设你遇到的问题是做一个IOC容器,如何开始?
Java代码 复制代码
  1. public interface BeanFactory {   
  2.   
  3.     String FACTORY_BEAN_PREFIX = "&";   
  4.   
  5.     Object getBean(String name) throws BeansException;   
  6.   
  7.     Object getBean(String name, Class requiredType) throws BeansException;   
  8.   
  9.     boolean containsBean(String name);   
  10.   
  11.     boolean isSingleton(String name) throws NoSuchBeanDefinitionException;   
  12.   
  13.     Class getType(String name) throws NoSuchBeanDefinitionException;   
  14.   
  15.     String[] getAliases(String name);   
  16. }  


BeanFactory是spring与容器交互最基本的一个描述,即我们需要从容器中得到一个实体类,判断它是否存在,是否是单例,又或是它的类型是什么样的。

一个类一个责任:

这是一条很简单的设计原则,但很难把握
Spring中的IOC容器设计,由 BeanFactory提供一个基本的描述,然后由其它接口描述其主要组件的功能,再由具体的子类逐层实现。每个类都有很清晰的责任,这样做复用性很好,而且阅读起来结构非常的清晰

我们从上至下,先看一下DefaultSingletonBeanRegistry这个类

SingletonBeanRegistry接口描述了对Bean一系列的操作
DefaultSingletonBeanRegistry是它的实现类

3个Map,其中singletonCache,disposableBeans是LinkedHashMap, dependentBeanMap只是普通的map。
Java代码 复制代码
  1. private final Map singletonCache    
  2. private final Map disposableBeans   
  3. private final Map dependentBeanMap = new HashMap();  


LinkedHashMap(详见Think in Java)
LinkedHashMap散列化所有的元素,但是在遍历“键值对”时,却又以元素的插入顺序返回“键值对”(println()会迭代遍历该映射,由此可以看到遍历的结果)。此外,可以在构造器中设定LinkedHashMap,使之采用给予访问的“最近最少使用”(LRU)算法,于是没有被访问过的(可以看作需要删除的)元素就会出现在队列的前面。对于需要定期清理元素以节省空间的程序来说,此功能使得程序很容易得以实现。

首先想看的就是spring是如何保存一个bean的。
在这个registerSingleton方法中,我们只是将类放入到了一个Map中,而Bean的创建是由其子类完成的。
如同它的名字registerSingleton只负责Bean的注册(保存到Map中)和Bean的销毁(从map中移除,并调用其相应的destory()方法
Java代码 复制代码
  1. // 注册一个实体类   
  2. public void registerSingleton(String beanName, Object sharedBean)    
  3.         //先判断是否存在,然后在添加,即把类放入singletonCache这个map中   
  4. Object oldObject = this.singletonCache.get(beanName);   
  5.             if (oldObject != null) {…}   
  6.         addSingleton(beanName, sharedBean);   
  7.     }   
  8.   
  9. //如果一个bean,它的产生依赖其它类,那么会使用这个方法,同样依赖类会被放入到dependentBeanMap中   
  10. public void registerDependentBean(String beanName, String dependentBeanName)   


spring中bean的生命周期经历了很多阶段,DispposableBean接口实现的是Bean的销毁过程,如果Bean实现了该接口,将会在创建过程中进行注册
Java代码 复制代码
  1. // 将BeanName放入disposableBeans这个Map中   
  2. public void registerDependentBean(String beanName, String dependentBeanName)       
  3.            
  4. // 得到一个类有2种方法直接从map中取出或由一个工厂类提供(考虑到工厂产生类的情况)   
  5. public Object getSingleton(String beanName) {   
  6.   
  7. public Object getSingleton(String beanName, ObjectFactory singletonFactory)   


最后,从容器中移除,destroySingleton,destroyBean两个方法递归调用,即不但要销毁这个bean,其对应的DisposableBean,调用destory()方法。而且如果这个类有依赖类,那么还要继续搜索,销毁其依赖类

Java代码 复制代码
  1. public void destroySingleton(String beanName) {   
  2.         //从map中将bean移除   
  3.         removeSingleton(beanName);   
  4.   
  5.         //移除相关的DisposableBean实例   
  6.         DisposableBean disposableBean = null;   
  7.         synchronized (this.disposableBeans) {   
  8.             disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);   
  9.         }   
  10.         destroyBean(beanName, disposableBean);   
  11.     }   
  12.   
  13.   
  14.     protected void destroyBean(String beanName, DisposableBean bean) {   
  15.         Set dependencies = null;   
  16.         synchronized (this.dependentBeanMap) {   
  17.          //在这里寻找是否有依赖类,然后调用destroySingleton方法   
  18.             dependencies = (Set) this.dependentBeanMap.remove(beanName);   
  19.         }   
  20.   
  21.         if (dependencies != null) {   
  22.             if (logger.isDebugEnabled()) {   
  23.                 logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);   
  24.             }   
  25.             for (Iterator it = dependencies.iterator(); it.hasNext();) {   
  26.                 String dependentBeanName = (String) it.next();   
  27.                 destroySingleton(dependentBeanName);   
  28.             }   
  29.         }   
  30.   
  31.         if (bean != null) {   
  32.             try {   
  33.                 bean.destroy();   
  34.             }   
  35.             catch (Throwable ex) {   
  36.                 logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);   
  37.             }   
  38.         }   
  39.     }   
  40.   
  41. }