概述
在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