SpringIoC初始化BeanDefinition解析——注册
来源:互联网 发布:福彩3d矩阵图 编辑:程序博客网 时间:2024/06/05 12:53
SpringIoC初始化BeanDefinition解析——注册
BeanDefinition的解析还差最后的注册过程,距离前两篇文章隔的有点久,现在补上。
先来回顾一下上一篇文章里提到了DefaultBeanDefinitionDocumentReader中的方法:
<span style="font-weight: normal;"><span style="font-size:18px;">protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance.BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// Send registration event.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}</span></span>
这个方法通过BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())进行BeanDefinition的注册。BeanDefinition被包装在bdHolder中,而registry是从ReaderContext中取得的。这个registry就是spring注册bean定义的注册中心,所有的bean都要注册到这个注册中心去。这个registry到底是什么东西呢,这要要从XmlBeanDefinitionReader的创建说起,再回顾下第一篇文章中XmlWebApplicationContext触发BeanDefinition解析的方法
<span style="font-weight: normal;"><span style="font-size:18px;">protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setEnvironment(this.getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);}</span></span>
创建XmlBeanDefinitionReader的时候传入的了一个beanFactory。这个beanFactory其实就是刚刚提到的注册中心registry。下面的代码印证了这个事实
<span style="font-weight: normal;"><span style="font-size:18px;">public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {super(registry);}</span></span>
<span style="font-weight: normal;"><span style="font-size:18px;">public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable</span></span>
DefaultListableBeanFactory 就是BeanDefinitionRegistry得子类,容器在创建XmlBeanDefinitionReader的时候把自己的beanFactory作为构造函数的参数传给了XmlBeanDefinitionReader,然后XmlBeanDefinitionReader在构造ReaderContext的时候又将自己传给了ReaderContext。
<span style="font-weight: normal;"><span style="font-size:18px;">protected XmlReaderContext createReaderContext(Resource resource) {if (this.namespaceHandlerResolver == null) {this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();}return new XmlReaderContext(resource, this.problemReporter, this.eventListener,this.sourceExtractor, this, this.namespaceHandlerResolver);}</span></span>
而ReaderContext中获取registry就是取的XmlBeanDefinitionReader中的registry。
<span style="font-size:18px;">public final BeanDefinitionRegistry getRegistry() {return this.reader.getRegistry();}</span>
注册中心DefaultListableBeanFactory主要靠维护一个hashmap来保存所有的BeanDefinition,hashmap的key就是bean的名字。下面节选自DefaultListableBeanFactory的代码:
<span style="font-size:18px;">/** Map of bean definition objects, keyed by bean name */private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();</span>
说了这么多还没有解释注册的方法,下面就是BeanDefinitionReaderUtils的registerBeanDefinition方法:
<span style="font-size:18px;">public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String aliase : aliases) {registry.registerAlias(beanName, aliase);}}}</span>这里做了两件事,第一件事利用registry把bean的名字和BeanDefinition注册进去,另外就是把所有bean的别名也进行了注册。接下来看看registry是怎么对bean的名字和bean的别名进行注册的:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}synchronized (this.beanDefinitionMap) {Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);if (oldBeanDefinition != null) {if (!this.allowBeanDefinitionOverriding) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +"': There is already [" + oldBeanDefinition + "] bound.");}else {if (this.logger.isInfoEnabled()) {this.logger.info("Overriding bean definition for bean '" + beanName +"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");}}}else {this.beanDefinitionNames.add(beanName);this.frozenBeanDefinitionNames = null;}this.beanDefinitionMap.put(beanName, beanDefinition);resetBeanDefinition(beanName);}}
public void registerAlias(String name, String alias) {Assert.hasText(name, "'name' must not be empty");Assert.hasText(alias, "'alias' must not be empty");if (alias.equals(name)) {this.aliasMap.remove(alias);}else {if (!allowAliasOverriding()) {String registeredName = this.aliasMap.get(alias);if (registeredName != null && !registeredName.equals(name)) {throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +name + "': It is already registered for name '" + registeredName + "'.");}}checkForAliasCircle(name, alias);this.aliasMap.put(alias, name);}}
0 0
- SpringIoC初始化BeanDefinition解析——注册
- SpringIoC初始化BeanDefinition解析——从Resource到BeanDefinition
- SpringIoC初始化BeanDefinition解析——Resource的定位
- SpringIOC--初始化源码解析
- SpringIOC--初始化源码解析
- SpringIOC--初始化源码解析
- 【Spring Framework 深入】—— IoC容器初始化 -> BeanDefinition的注册
- SpringIoc BeanDefinition载入交互过程
- bean标签的解析及注册(二)解析BeanDefinition
- 解析BeanDefinition。
- Spring源码解析-BeanDefinition在IOC容器中的注册(三)
- spring源码(8)注册解析的BeanDefinition
- bean标签的解析及注册(四)注册解析的beanDefinition
- Spring源码阅读之IoC容器初始化3 -- BeanDefinition在IoC容器中的注册
- spring 技术内幕--IOC初始化之BeanDefinition的在IOC容器中的注册
- spring技术内幕笔记:IoC容器的初始化过程(3)- BeanDefinition的注册
- SpringIOC的初始化
- Spring BeanDefinition及读取、注册
- 三个油瓶分油问题
- 用STL中的map容器实现从很多单词找出所有只有一个字母不同的单词
- Cocoa框架图
- iOS---自定义带占位文字placeholder的TextView
- c++11 宽字节与窄字节的相互转换
- SpringIoC初始化BeanDefinition解析——注册
- NDK浅尝(1)
- c++11 时间戳
- 理解矩阵
- 富翁手机游戏开发实战----书中代码下载地址
- C语言--指针的使用
- CentOS6下SVN服务器的搭建
- 数据结构小结
- JAVA中,嵌套类的介绍