Spring 源码 Bean Definition 注册

本文详细讲解了Spring中BeanDefinition注册过程,包括BeanDefinition验证、注册策略和BeanDefinition刷新,重点展示了如何处理BeanName冲突及BeanDefinition更新操作。

        Spring中调用一个BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())方法把bean的definition描述注册。

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		// 获取 beanName
		String beanName = definitionHolder.getBeanName();
		// 注册bean definition
		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);
			}
		}
	}

下面我们看核心registerBeanDefinition的逻辑

第一部分definition的验证

// 第一部分 Bean Definition 的验证
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				// bean定义验证
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

第二部分  Bean Name 在容器中的不同情况处理。

  • 情况一: Bean Name 已经在容器中存在,并且拥有对应的 Bean Definition 对象。
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			// bean name 是否允许重复注册,判断是否允许覆盖 Bean Definition
			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 + "]");
				}
			}
			// map 中存储的 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 + "]");
				}
			}
			// 设置 beanName 和 beanDefinition 关系
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
  • 情况二:Bean Name 在容器中搜索 Bean Definition 失败。
		else {
			// 检查 bean 是否已经开始创建
			// return !this.alreadyCreated.isEmpty();
			// 在 Spring 中有一个叫做 markBeanAsCreated 的方法,这个方法就是用来标记 Bean 正在被创建。
			// 在 Get Bean 的时候alreadyCreated会被赋值,在 Create Bean 的时候会被赋值。
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					// 设置 beanName 和 beanDefinition 关系
					this.beanDefinitionMap.put(beanName, beanDefinition);
					// bean definition 的名称列表
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					// 加入内存数据
					updatedDefinitions.addAll(this.beanDefinitionNames);
					// 加入当前的 beanName
					updatedDefinitions.add(beanName);
					// 对象替换
					this.beanDefinitionNames = updatedDefinitions;
					// 移除当前手工注册的beanName
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				// 设置容器数据
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				// 移除当前手工注册的beanName
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

第三部分 根据 Bean Name 进行 Bean Definition 的刷新操作。


		if (existingDefinition != null || containsSingleton(beanName)) {
			// 第一个条件:通过 Bean Name 搜索 Bean Definition 搜索成功
			// 第二个条件:单例对象容器中包含当前 Bean Name 的实例对象
			// 刷新bean definition
			resetBeanDefinition(beanName);
		}

在整个 resetBeanDefinition 方法中分为下面几个步骤

  1. 将合并的 Bean Definition ( mergedBeanDefinitions ) 中可能存在 Bean Definition 中的 stale 属性设置为 true
  2. 摧毁当前 Bean Name 对应的单例实例
  3. MergedBeanDefinitionPostProcessor 的后置方法执行
  4. 处理 Bean Definition 名称列表中名称和当前 Bean Name 相同的数据
	protected void resetBeanDefinition(String beanName) {
		// Remove the merged bean definition for the given bean, if already created.
		// mergedBeanDefinition 的本质还是 Bean Definition ,在这里主要以 RootBeanDefinition  类型出现
		// 合并的是 父 Bean Definition 对象和 当前的 Bean Definition
		// 一个BeanDefinition是可以设置父类BeanDefinition的, 仅仅需要调用其setParentName即可, 之所以出现父子
		// bean是因为Spring允许将相同bean的定义给抽出来, 成为一个父BeanDefinition, 这样其它的BeanDefinition
		// 就能共用这些公共的数据了, 并且提出了RootBeanDefinition和ChildBeanDefinition之间的关系, 以及他们
		// 的缺点, 从而Spring在之后的版本中引入了GenericBeanDefinition, 在Spring的生命周期中, 如果要实例化
		// 一个bean则需要先将bean进行合并, 这样拿到的BeanDefinition才是信息完整的
		clearMergedBeanDefinition(beanName);

		// Remove corresponding bean from singleton cache, if any. Shouldn't usually
		// be necessary, rather just meant for overriding a context's default beans
		// (e.g. the default StaticMessageSource in a StaticApplicationContext).
		// 从单例容器中将当前 Bean Name 从容器中剔除。
		destroySingleton(beanName);

		// Notify all post-processors that the specified bean definition has been reset.
		// 其实 MergedBeanDefinitionPostProcessor 是 BeanPostProcessor 的子接口,
		// 后置处理器执行 resetBeanDefinition 方法
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			if (processor instanceof MergedBeanDefinitionPostProcessor) {
				// 执行后置方法的 resetBeanDefinition
				((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
			}
		}

		// Reset all bean definitions that have the given bean as parent (recursively).
		// 递归处理,处理的目标是在 Bean Definition 的名称列表中和当前正在处理的 Bean Name 相同
		for (String bdName : this.beanDefinitionNames) {
			if (!beanName.equals(bdName)) {
				BeanDefinition bd = this.beanDefinitionMap.get(bdName);
				// Ensure bd is non-null due to potential concurrent modification of beanDefinitionMap.
				// beanName 等于 父名称,说明没有父类了,如果不等于,说明还有,那么就递归调用
				if (bd != null && beanName.equals(bd.getParentName())) {
					// 递归刷新 beanName 对应的 beanDefinition
					resetBeanDefinition(bdName);
				}
			}
		}
	}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值