(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王国里,它就是富二代。

时间: 2024-11-08 18:28:44

(spring-第8回【IoC基础篇】)BeanDefinition在IoC容器中的注册的相关文章

(spring-第13回【IoC基础篇】)PropertyEditor(属性编辑器)--实例化Bean的第五大利器

上一篇讲到JavaBeans的属性编辑器,编写自己的属性编辑器,需要继承PropertyEditorSupport,编写自己的BeanInfo,需要继承SimpleBeanInfo,然后在BeanInfo中把特定的属性编辑器和需要编辑的属性绑定起来(详情请查看上一篇). Spring的属性编辑器仅负责将配置文件中的字面值转换成Bean属性的对应值.(而JavaBean的属性编辑器能够通过界面来手动设置bean属性的值).如果属性的类型不同,转换的方法就不同.正如javabean的属性编辑器一样,

(spring-第7回【IoC基础篇】)BeanDefinition的载入与解析&amp;&amp;spring.schemas、spring.handlers的使用

报错信息:Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/p], 一桩事故引发的连锁思考...开幕—— ----------------------------------------------------------------------------------------------

(spring-第9回【IoC基础篇】)BeanFactoryPostProcessor,实例化Bean之前的第二大利器

继承结构图如上.在加载XML,注册bean definition之后,在实例化bean definition之前,必要的时候要用到BeanFactoryPostProcessor.它负责把XML中有些占位符式的属性还原成真实值.意思是说,有时候,XML中<bean>的属性值不固定,会随着外界因素变化,这时候,在<bean>中配置占位符,而另外定义一个属性文件来控制<bean>的属性.比如下面是一个数据库连接的XML配置: 1 <bean id="data

(spring-第14回【IoC基础篇】)国际化信息 (转)

国际化又称为本地化. 当你把手机的language由中文切换到英文时,你的微信也相应改用英语,这就是i18n国际化.一般来说,应用软件提供一套不同语言的资源文件,放到特定目录中,应用根据不同语言的操作系统决定使用哪一种语言. 一般由两个条件限定一个国际化类型:语言类型和国家/地区类型.比如: 中文:语言类型:zh,国家/地区类型:CN(中国大陆)/HK(中国香港)/TW(中国台湾). 英语:语言类型:en,国家类型:EN. ------------------------------------

(spring-第14回【IoC基础篇】)国际化信息

国际化又称为本地化. 当你把手机的language由中文切换到英文时,你的微信也相应改用英语,这就是i18n国际化.一般来说,应用软件提供一套不同语言的资源文件,放到特定目录中,应用根据不同语言的操作系统决定使用哪一种语言. 一般由两个条件限定一个国际化类型:语言类型和国家/地区类型.比如: 中文:语言类型:zh,国家/地区类型:CN(中国大陆)/HK(中国香港)/TW(中国台湾). 英语:语言类型:en,国家类型:EN. ------------------------------------

(spring-第10回【IoC基础篇】)InstantiationStrategy--实例化Bean的第三大利器

Bean的实例化整个过程如下图: : 其中,BeanDefinition加入到注册表中,并由BeanFactoryPostProcessor的实现类处理后,需要由InstantiationStrategy负责实例化.实例化仅仅是调用构造函数,相当于new了一个对象而已,bean的具体的属性在此时并未赋值(当然,一开始在XML中配置了Bean属性的值,或者在构造函数中有赋值语句的话,相关属性才会在实例化的时候便有了值.).InstantiationStrategy负责由Bean类的默认构造函数.带

JAVA基础篇八(Java,C++中的网络)

基础篇写到这里,C++和JAVA的基础知识也要讲完了,至于更深入的使用,则需要单独寻找每种语言特有的类库. 讲到网络,不可避免地要讲TCP/IP的基本使用方法.本文只对两种语言的网络实现做简单介绍,后续学习中如果有详细说明,会逐步添加到本文中. 1.C++网络知识 简单的TCP/IP: server端: #include <WINSOCK2.H> #include <stdio.h> #pragma comment(lib,"ws2_32.lib") void

(spring-第12回【IoC基础篇】)JavaBean的属性编辑器

在spring实例化bean的最后阶段,spring利用属性编辑器将配置文件中的文本配置值转换为bean属性的对应值,例如: 代码0011 <bean id="car" class="com.mesopotamia.test1.Car" 2 p:name="汽车" 3 p:brand="宝马" 4 p:maxSpeed="200"/> 上面是文本配置, 再看bean: 代码0021 public

(spring-第15回【IoC基础篇】)容器事件

五个人在报社订阅了报纸.报社一旦有了新报纸,就派员工分别送到这五个人手里.在这个例子中,“报纸”就是事件,“报社”就是广播器,五个订阅者就是监听器.广播器收到事件,把事件传给监听器,监听器对事件做一些事情.这样的例子属于观察者模式. 观察者模式:A类负责接收新信息,B.C.D类一直关注着A.A类一旦有了新信息,就发送给B.C.D类,B.C.D类收到信息作出不同的操作.这就是观察者模式.具体到代码中,A中设置一个变量message(这就是信息),当message改变时,调用B.C.D的perfor