(spring-第8回【IoC基础篇】)BeanDefinition在IoC容器中的注册
在spring中,所有的bean都是由BeanFactory进行管理的。下面是BeanFactory的类体系结构:
我们清楚的看到,DefaultListableBeanFactory继承了BeanFactory的优良传统,同时又实现了BeanDefinitionRegistry这个注册器,那么无疑,BeanDefinition在容器中的注册任务,非他莫属。事实上,DefaultListableBeanFactory拥有一个私有的BeanDefinitonMap属性,这个属性是个哈希Map,通过把解析好的BeanDefiniton放到哈希Map中,就完成了注册。下面是注册方法:
1 //--------------------------------------------------------------------- 2 // Implementation of BeanDefinitionRegistry interface 3 //--------------------------------------------------------------------- 4 5 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 6 throws BeanDefinitionStoreException { 7 8 。。。。。。40 41 this.beanDefinitionMap.put(beanName, beanDefinition); 42 43 44 resetBeanDefinition(beanName); 45 } 46 }
第41行把beanDefinition作为value,而把beanName作为key,放到beanDefinitionMap中,就完成了注册。那么,这个beanDefinition是从哪里传过来的呢?
由于我的myeclipse环境中使用的是spring源码,而非jar包,所以我们做一个小测试,我配置一个简单的<bean>,然后做一个恶简单的spring容器的启动和<bean>的加载,那么程序一定会走到41行来执行注册。我在第41行上面加上一句:beanDefinition=null;这样的话,执行到第41行就会报错,报错信息如下:
。。。。。。 17 Caused by: java.lang.NullPointerException 18 at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:881) 19 at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:628) 20 at org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerBeanDefinition(BeanDefinitionReaderUtils.java:148) 21 at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition(DefaultBeanDefinitionDocumentReader.java:263) 22 at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.java:153) 23 at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:132) 24 at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93) 25 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493) 26 at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390) 27 ... 14 more
从第26行倒着往上看,就是整个beanDefinition的加载与注册过程。大概过程我们一目了然:
1.由XmlBeanDefinitionReader开始加载、注册。
2.由DefaultBeanDefinitionDocumentReader开始解析。
3.由BeanDefinitionReaderUtils过渡。
4.由DefaultListableBeanFactory注册。
我们来具体分析一下这四个类。
解读第1步:Resource在加载了XML文件后,首先是由BeanDefinitionReader来解析的。下面是BeanDefinitionReader的部分子孙图和注释:
解读第2步:那么第二步所说的DefaultBeanDefinitionDocumentReader应该就是图中提到的"BeanDefinitionDocumentReader"的某个子孙了。它负责与BeanDefinitionRegistry的实现者对话。而这个"BeanDefinitionRegistry的实现者"就是DefaultListableBeanFactory。
BeanDefinitionDocumentReader的家族图也很简单,它的家谱图说明:
解读第3步:过渡类。
解读第4步:文章一开始已经分析过了。实际上,DefaultListableBeanFactory能做的事情很多,除了注册BeanDefinition外,它可以被用作一个独立的BeanFactory,又可以被基本的BeanFactory子类来继承,打开API文档你会看到,DefaultListableBeanFactory继承和实现了一堆父类,亲爹干爹一大堆,API上描述其为:"a full-fledged bean factory"(羽翼丰满的bean factory),下面是它的亲爹和干爹们:
没错,在spring王国里,它就是富二代。