什么是MergedBeanDefinition?

对Spring有一定熟悉的人都知道在Spring中用BeanDefinition来代表一个Spring对象的定义。因此有BeanDefinitionBuilderBeanDefinitionParser这些常见工具类。简单来说,整个Spring容器也就是读取文件、构造BeanDefinition对象、实例化成Bean的过程。BeanDefinition也可以认为是一个Bean元数据的容器,包含了一个bean实例化和初始化所需要的各种参数,比如class、name、scope、properties等等。
比如说

<bean id="exampleBean" class="examples.ExampleBean"/>

这就代表了一个BeanDefinition对象。

查看Spring源码中相关类的结构
在这里插入图片描述
但是会发现,不存在一个叫MergedBeanDefinition的类?
ConfigurableBeanFactory中有一个方法getMergedBeanDefinition,方法定义如下:

/**
 * Return a merged BeanDefinition for the given bean name,
 * merging a child bean definition with its parent if necessary.
 * Considers bean definitions in ancestor factories as well.
 * @param beanName the name of the bean to retrieve the merged definition for
 * @return a (potentially merged) BeanDefinition for the given bean
 * @throws NoSuchBeanDefinitionException if there is no bean definition with the given name
 * @since 2.5
 */
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

从注释可以看出这个方法根据给定的Bean名称返回一个merged的,嗯,混合的BeanDefinition对象,在必要的时候,会合并父子Bean定义。
方法实现如下所示:

@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
	String beanName = transformedBeanName(name);
	// Efficiently check whether bean definition exists in this factory.
	if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
		return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
	}
	// Resolve merged bean definition locally.
	return getMergedLocalBeanDefinition(beanName);
}

首先查询缓存mergedBeanDefinitions

/** Map from bean name to merged RootBeanDefinition. */
	private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
/**
 * 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;
	}
	// 首先获取到原来的bean定义
	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 {@code 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 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) {
				// Use copy of given root bean definition.
				if (bd instanceof RootBeanDefinition) {
					mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
				}
				else {
					mbd = new RootBeanDefinition(bd);
				}
			}
			else {
				// 存在父Bean定义
				// Child bean definition: needs to be merged with parent.
				BeanDefinition pbd;
				try {
				    // 查找真实名称 
					String parentBeanName = transformedBeanName(bd.getParentName());
					// 查找pdb
					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.
				// 首先根据pdb创建RootBeanDefinition对象 然后再用原来的bd覆盖
				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);
			}

			// 非单例Bean包含的不可能是单例Bean
			// 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;
	}
}

以下 mbd = MergedBeanDefinition,bd = bean definition

从以上代码可以看出,用于代表mdb的是类RootBeanDefinition,通常代表的是一个通过多个相关继承关系的bean definitions合并的bd。通常我们注册的bean都是GenericBeanDefinition类型的,RootBeanDefinition作为统一的bd视图而存在。
比如说存在以下的bean定义

package example;

import java.util.Properties;

public class ComplexObject {

    private Properties properties;

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="parent" abstract="true" class="example.ComplexObject">
        <property name="adminEmails">
            <props>
                <prop key="administrator">administrator@example.com</prop>
                <prop key="support">support@example.com</prop>
            </props>
        </property>
    </bean>
    <bean id="child" parent="parent">
        <property name="adminEmails">
            <!-- the merge is specified on the child collection definition -->
            <props merge="true">
                <prop key="sales">sales@example.com</prop>
                <prop key="support">support@example.co.uk</prop>
            </props>
        </property>
    </bean>

</beans>

编写主类

package com.example.managingtransactions;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import org.springframework.stereotype.Component;

@ImportResource("classpath:applicationContext.xml")
@SpringBootApplication
public class ManagingTransactionsApplication {

	@Autowired
	private BeanFactory beanFactory;

    public static void main(String[] args) {
        SpringApplication.run(ManagingTransactionsApplication.class, args);

    }

    @Component
	class AppRunner implements CommandLineRunner{
		@Override
		public void run(String... args) throws Exception {
			DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
			BeanDefinition mbd = defaultListableBeanFactory.getMergedBeanDefinition("child");
			BeanDefinition bd = defaultListableBeanFactory.getBeanDefinition("child");
			System.out.println(bd);
		}
	}
}

debug如下:
在这里插入图片描述
可见mbd和bd不一样。
另外bd中获取的属性如下:
在这里插入图片描述
也就是只包含了以下内容:

<props merge="true">
    <prop key="sales">sales@example.com</prop>
    <prop key="support">support@example.co.uk</prop>
</props>

而mdb中有3条,因为有一个key值support在子bd和父bd中重复,子的覆盖了父的。

<props merge="true">
    <prop key="administrator">administrator@example.com</prop>
    <prop key="support">support@example.com</prop>   <!--这一条被覆盖-->
    <prop key="sales">sales@example.com</prop>
    <prop key="support">support@example.co.uk</prop>
</props>

在这里插入图片描述
以上说明了mbd存在的主要原因:解决存在继承关系的多个bd的合并问题。当然也可以获取父bd
在这里插入图片描述
从某种意义上来说,mdb所包含的信息更完整(只不过平常我们使用这种继承关系比较少)。因此在创建Bean的时候,我们传入的参数也是mbd,如下所示:
在这里插入图片描述
在这里插入图片描述
另外在Spring中有一个专门针对mbd的后置处理器MergedBeanDefinitionPostProcessor.
在对一个Bean实例化(构造或者工厂方法)之后,会调用这个后置处理器,对应的源码如下:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
	Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			mbd.postProcessed = true;
		}
	}
	// 以下进保留注释 其他源码省略
	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	// Initialize the bean instance.
	// Register bean as disposable.
	return exposedObject;
}
/**
 * Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
 * invoking their {@code postProcessMergedBeanDefinition} methods.
 * @param mbd the merged bean definition for the bean
 * @param beanType the actual type of the managed bean instance
 * @param beanName the name of the bean
 * @throws BeansException if any post-processing failed
 * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
 */
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
		throws BeansException {

	try {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}
	catch (Exception ex) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Post-processing failed of bean type [" + beanType + "] failed", ex);
	}
}

此时对应的Bean对象已经实例化,但是还没有进行初始化,因此可以用于修改一些定义的属性或者加载一些元数据信息,通常不建议通过这个类来修改属性。比如在InitDestroyAnnotationBeanPostProcessor中用于加载生命周期元数据

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	if (beanType != null) {
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		metadata.checkConfigMembers(beanDefinition);
	}
}

CommonAnnotationBeanPostProcessor中加载@Resource注解元数据

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	if (beanType != null) {
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType);
		metadata.checkConfigMembers(beanDefinition);
	}
}

从以上不难看出,mbd代表一个bean定义更完整。类RootBeanDefinitionGenericBeanDefinion包含的属性更多。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lang20150928

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值