您的位置:首页 > 编程语言 > Java开发

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);
		}
	}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: