Spring的bean定义 4 : 合并了的bean定义--MergedBeanDefinition

概述

Spring中,关于bean定义,其Java建模模型是接口BeanDefinition, 其变种有RootBeanDefinitionChildBeanDefinition,还有GenericBeanDefinitionAnnotatedGenericBeanDefinition,ScannedGenericBeanDefinition等等。这些概念模型抽象了不同的关注点。关于这些概念模型,除了有概念,也有相应的Java建模模型,甚至还有通用的实现部分AbstractBeanDefinition。但事实上,关于BeanDefinition,还有一个概念也很重要,这就是MergedBeanDefinition(中文也许应该翻译成"合并了的bean定义"?),但这个概念并没有相应的Java模型对应。但是它确实存在,并且Spring专门为它提供了一个生命周期回调定义接口MergedBeanDefinitionPostProcessor用于扩展。

MergedBeanDefinition的生成

我们先从代码看一个MergedBeanDefinition是怎么生成的 ? 下面是类AbstractBeanFactorybean获取方法doGetBean()的伪代码 :

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	// ...
	// 这里根据bean名称获取MergedBeanDefinition,结果类型是RootBeanDefinition 
	final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
	// ...		
	createBean(beanName, mbd, args);
	
	// ...
}

从上面代码可见,通过方法getMergedLocalBeanDefinition(),一个RootBeanDefinition mbd根据bean名称生成了。我们进而跟踪getMergedLocalBeanDefinition的实现。如下 :

	/**
	 * Return a merged RootBeanDefinition, traversing the parent bean definition
	 * if the specified bean corresponds to a child bean definition.
	 * @param beanName the name of the bean to retrieve the merged definition for
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */
	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) 
	throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

	/**
	 * Return a RootBeanDefinition for the given top-level bean, by merging with
	 * the parent if the given bean's definition is a child bean definition.
	 * @param beanName the name of the bean definition
	 * @param bd the original bean definition (Root/ChildBeanDefinition)
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */	
	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
			throws BeanDefinitionStoreException {

		return getMergedBeanDefinition(beanName, bd, null);
	}

	/**
	 * Return a RootBeanDefinition for the given bean, by merging with the
	 * parent if the given bean's definition is a child bean definition.
	 * @param beanName the name of the bean definition
	 * @param bd the original bean definition (Root/ChildBeanDefinition)
	 * @param containingBd the containing bean definition in case of inner bean,
	 * or null in case of a top-level bean
	 * @return a (potentially merged) RootBeanDefinition for the given bean
	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
	 */		
	protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

		synchronized (this.mergedBeanDefinitions) {
			// 准备一个RootBeanDefinition变量引用,用于记录要构建和最终要返回的BeanDefinition,
			// 这里根据上下文不难猜测 mbd 应该就是 mergedBeanDefinition 的缩写。
			RootBeanDefinition mbd = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null) {
				if (bd.getParentName() == null) {
					// bd不是一个ChildBeanDefinition的情况,换句话讲,这 bd应该是 :
					// 1. 一个独立的 GenericBeanDefinition 实例,parentName 属性为null
					// 2. 或者是一个 RootBeanDefinition 实例,parentName 属性为null
					// 此时mbd直接使用一个bd的复制品
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {						
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// bd是一个ChildBeanDefinition的情况,
					// 这种情况下,需要将bd和其parent bean definition 合并到一起,
					// 形成最终的 mbd
					// 下面是获取bd的 parent bean definition 的过程,最终结果记录到 pbd,
					// 并且可以看到该过程中递归使用了getMergedBeanDefinition(), 为什么呢?
					// 因为 bd 的 parent bd 可能也是个ChildBeanDefinition,所以该过程
					// 需要递归处理
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
						String parentBeanName = transformedBeanName(bd.getParentName());
						if (!beanName.equals(parentBeanName)) {
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {
							BeanFactory parent = getParentBeanFactory();
							if (parent instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) 
									parent).getMergedBeanDefinition(parentBeanName);
							}
							else {
								throw new NoSuchBeanDefinitionException(parentBeanName,
										"Parent name '" + parentBeanName + 
										"' is equal to bean name '" + beanName +
							"': cannot be resolved without an AbstractBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(
							bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + 
								bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
					// 现在已经获取 bd 的parent bd到pbd,从上面的过程可以看出,这个pbd
					// 也是已经"合并"过的。
					// 这里根据pbd创建最终的mbd,然后再使用bd覆盖一次,
					// 这样就相当于mbd来自两个BeanDefinition:
					// 当前 BeanDefinition 及其合并的("Merged")双亲 BeanDefinition,
					// 然后mbd就是针对当前bd的一个MergedBeanDefinition(合并的BeanDefinition)了。
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original 
				// inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// Cache the merged bean definition for the time being
				// (it might still get re-merged later on in order to pick up metadata changes)
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}

			return mbd;
		}
	}

从上面的MergedBeanDefinition的获取过程可以看出,一个MergedBeanDefinition其实就是一个"合并了的BeanDefinition",最终以RootBeanDefinition的类型存在。

看完MergedBeanDefinition的生成,我们接下来看它的作用。从上面的代码中,我们也可以看到一个MergedBeanDefinition被根据bean名称获取之后,传递到了方法createBean()用于创建bean

MergedBeanDefinition的应用

下面是类AbstractAutowireCapableBeanFactorybean创建方法createBean()的实现,可以看到,针对传入的参数RootBeanDefinition mbd,也就是上面生成的MergedBeanDefinition,专门有一个applyMergedBeanDefinitionPostProcessors()调用,这里就是容器中注册的MergedBeanDefinitionPostProcessor的应用阶段 :

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 
	final @Nullable Object[] args)	throws BeanCreationException {
        // ...

		// 创建bean POJO 对象
		instanceWrapper = createBeanInstance(beanName, mbd, args);

		 // ...        
		 
	    // 修改 merged bean definition 的 BeanPostProcessor 的执行	
        // ==== 调用 MergedBeanDefinitionPostProcessor ====
		applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 
		
       // ...

	   // 填充 bean 属性:依赖注入处理,属性设置
	   populateBean(beanName, mbd, instanceWrapper);

       // ...
	   
	   // 初始化 bean : 调用设置的初始化方法,接口定义的初始化方法,
	   // 以及相应的 pre-/post-init 生命周期回调函数
	   initializeBean(beanName, exposedObject, mbd);       

	   // ...

	   // 如果当前 bean 实现类有关销毁时的接口或者函数,将它进行相应的登记
	   // 供容器关闭时执行相应的回调函数	
       registerDisposableBeanIfNecessary(beanName, bean, mbd);                   
}

方法applyMergedBeanDefinitionPostProcessors()的实现如下:

	// 找到容器中注册的所有BeanPostProcessor中每一个MergedBeanDefinitionPostProcessor,
	// 将它们应用到指定的RootBeanDefinition mbd上,这里 mbd 其实就是一个 MergedBeanDefinition。
	protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, 
			Class<?> beanType, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

从上面代码的代码我们只能看到,MergedBeanDefinitionPostProcessor会被应用到bean,在它被填充属性之前。不过这还是有点抽象了,我们下面举一个例子,这里的作用就很清楚了:

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
	// ...		
	// 在每个bean实例化后,初始化前执行,获取并记录该bean属性注入的元数据,在随后的属性注入时使用
	// 该方法由接口MergedBeanDefinitionPostProcessor定义
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
		Class<?> beanType, String beanName) {
		// 获取指定bean的属性注入元数据
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
	// ...
}

上面的代码是Spring框架工具AutowiredAnnotationBeanPostProcessor的实现代码片段,该工具实现了MergedBeanDefinitionPostProcessor,它在一个beanpostProcessMergedBeanDefinition()阶段,如上代码所示,获取该bean的依赖注入元数据(哪些方法使用了@Autowired,@Inject,@Value等等),随后用于该bean属性填充中依赖注入执行阶段的输入。

总结

综上可见,一个MergedBeanDefinition是这样一个载体:

  1. 根据原始BeanDefinition及其可能存在的双亲BeanDefinition中的bean定义信息"合并"而得来的一个RootBeanDefinition
  2. 每个Bean的创建需要的是一个MergedBeanDefinition,也就是需要基于原始BeanDefinition及其双亲BeanDefinition信息得到一个信息"合并"之后的BeanDefinition
  3. Spring框架同时提供了一个机会给框架其他部分,或者开发人员用于在bean创建过程中,MergedBeanDefinition生成之后,bean属性填充之前,对该bean和该MergedBeanDefinition做一次回调,相应的回调接口是MergedBeanDefinitionPostProcessor
  4. MergedBeanDefinition没有相应的Spring建模,它是处于一个内部使用目的合并自其它BeanDefinition对象,其具体对象所使用的实现类类型是RootBeanDefinition

相关文章

Spring BeanPostProcessor : AutowiredAnnotationBeanPostProcessor
Spring的bean定义 1 : 基础建模–接口BeanDefinition
Spring的bean定义 2 : 通用bean定义逻辑 – AbstractBeanDefinition
Spring的bean定义 3 : BeanDefinition实现类例子演示
Spring的bean定义 4 : 合并了的bean定义–MergedBeanDefinition

  • 23
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值