概述
在Spring中,关于bean定义,其Java建模模型是接口BeanDefinition, 其变种有RootBeanDefinition,ChildBeanDefinition,还有GenericBeanDefinition,AnnotatedGenericBeanDefinition,ScannedGenericBeanDefinition等等。这些概念模型抽象了不同的关注点。关于这些概念模型,除了有概念,也有相应的Java建模模型,甚至还有通用的实现部分AbstractBeanDefinition。但事实上,关于BeanDefinition,还有一个概念也很重要,这就是MergedBeanDefinition(中文也许应该翻译成"合并了的bean定义"?),但这个概念并没有相应的Java模型对应。但是它确实存在,并且Spring专门为它提供了一个生命周期回调定义接口MergedBeanDefinitionPostProcessor用于扩展。
MergedBeanDefinition的生成
我们先从代码看一个MergedBeanDefinition是怎么生成的 ? 下面是类AbstractBeanFactory中bean获取方法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的应用
下面是类AbstractAutowireCapableBeanFactory中bean创建方法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,它在一个bean的postProcessMergedBeanDefinition()阶段,如上代码所示,获取该bean的依赖注入元数据(哪些方法使用了@Autowired,@Inject,@Value等等),随后用于该bean属性填充中依赖注入执行阶段的输入。
总结
综上可见,一个MergedBeanDefinition是这样一个载体:
- 根据原始
BeanDefinition及其可能存在的双亲BeanDefinition中的bean定义信息"合并"而得来的一个RootBeanDefinition; - 每个
Bean的创建需要的是一个MergedBeanDefinition,也就是需要基于原始BeanDefinition及其双亲BeanDefinition信息得到一个信息"合并"之后的BeanDefinition; Spring框架同时提供了一个机会给框架其他部分,或者开发人员用于在bean创建过程中,MergedBeanDefinition生成之后,bean属性填充之前,对该bean和该MergedBeanDefinition做一次回调,相应的回调接口是MergedBeanDefinitionPostProcessor。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

本文深入探讨Spring框架中MergedBeanDefinition的概念,解析其生成过程及应用,特别是在bean创建时如何通过MergedBeanDefinitionPostProcessor进行扩展。
1322

被折叠的 条评论
为什么被折叠?



