Spring技术内幕笔记(四)------IoC容器初始化过程#BeanDefinition在容器中的注册

Ioc容器的初始化过程

在上一篇中,我们已经分析过BeanDefinition在Ioc容器中的载入和解析过程,在经过以上步骤之后,用户所定义的BeanDefinition信息已经在IoC容器中建立起来自己的数据结构以及相应的数据表示,但是这些数据还是不能供IoC容器直接使用,我们需要将这些数据注册到IoC容器中。在DefaultListableBeanFactory中是通过一个ConcurrentHashMap来持有载入的BeanDefinition的。

在分析DefaultBeanDefinitionDocumentReader#registerBeanDefinitions方法的时候,这个方法是用来解析DOM定义的,其中通过调用doLoadBeanDefinitions方法进行在给定的根元素中注册每一个bean定义,那么注册的过程发生在什么地方呢?

registerBeanDefinitions —> parseBeanDefinitions—>parseDefaultElement—>processBeanDefinition

  1. processBeanDefinition
/**
	 * Process the given bean element, parsing the bean definition
	 and registering it with the registry.
	 处理给定的bean元素,解析bean定义并在注册表中注册
	 */
	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));
		}
	}

从源代码中我们可以发现,注册的过程发生在registerBeanDefinition中

	/**
	 * Register the given bean definition with the given bean factory.
	 给指定的bean工厂中注册指定的bean定义
	 @param definitionHolder the bean definition including name and aliases
	 包含bean的name和别名
	 @param registry the bean factory to register with
	 使用这个给bean工厂进行注册
	 @throws BeanDefinitionStoreException if registration failed
	 */
	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 alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

用于BeanDefinitionRegister是一个接口继承自AliasRegister,所以我们需要寻找它的子类DefaultListableBeanFactory是如何实现注册功能的

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		//断言bean名称必须不为空
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        //断言bean定义必须不为空
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

以上这个方法就是DefaultListableBeanFactory具体的注册方法。

总结:

  1. AbstractApplicationContext的refresh()方法定义容器初始化的整个流程,是一个模板方法,具体实现由子类完成
  2. 由AbstractApplicationContext的子类AbstractRefreshableApplicationContext对容器进行重启,创建一个新的容器,DefaultListableBeanFactory。
  3. 由于BeanDefinition的资源形式不同(XML,注解),所以需要不同的子类去继承AbstractRefreshableApplicationContext,来完成资源的定位工作,如AbstractXMLApplicationContext
  4. AbstractXMLApplicationContext本身是没有对资源定位和解析的功能的,由它创建BeanDefinitionReader,对资源进行定位,加载工作。
  5. BeanDefinitionReader完成定位和加载。首先获取到resource,通过resource得到InputStream,根据InputStream得到Document。然后创建BeanDefinitionDocumentReader。
  6. BeanDefinitionDocumentReader完成对xml的解析,获取BeanDefinitionHolder。
  7. 最后BeanDefinitionDocumentReader委托DefaultListableBeanFactory完成定义的注册。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值