对Spring有一定熟悉的人都知道在Spring中用BeanDefinition
来代表一个Spring对象的定义。因此有BeanDefinitionBuilder
、BeanDefinitionParser
这些常见工具类。简单来说,整个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定义更完整。类RootBeanDefinition
比GenericBeanDefinion
包含的属性更多。