SpringIoC初始化BeanDefinition解析——注册
2015-10-24 22:51
489 查看
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 AbstractAutowireCapableBeanFactory
implements 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); } }
相关文章推荐
- Java计算圆周率
- Spring事务配置的5种方式
- Java实现二叉树的构建与遍历
- 从头认识java-3.1 for each
- 从头认识java-3.1 for each
- Java Web 技术整合基础篇1 web产生及发展
- 实际项目中页面标签的使用
- 从头认识java-2.6 逗号操作符
- 从头认识java-2.6 逗号操作符
- JAVA大数运算
- 实例演示如何在spring4.2.2中集成hibernate5.0.2并创建sessionFactory
- 实例演示如何在spring4.2.2中集成hibernate5.0.2并创建sessionFactory
- 实例演示如何在spring4.2.2中集成hibernate5.0.2并创建sessionFactory
- java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/LoopTag 解决方法
- java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/LoopTag 解决方法
- java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/LoopTag 解决方法
- java 责任链模式
- [深入理解Java虚拟机]第七章 类加载器
- java.lang.IllegalArgumentException: Document base does not exist or is not a readable directory错误解决
- java中的char类型