0106MergedBeanDefinition处理和Bean属性赋值-Bean生命周期详解-spring
创始人
2025-05-29 16:08:36

文章目录

    • 1 MergedBeanDefinition 后置处理
      • 1.1 在哪里被调用执行?
      • 1.2 两个常用的实现类
        • 1.2.1 AutowiredAnnotationBeanPostProcessor
        • 1.2.2 CommonAnnotationBeanPostProcessor
    • 2 Bean 属性赋值
      • 2.1 实例化后阶段
      • 2.2 Bean 属性赋值前处理
      • 2.3 Bean 属性赋值
    • 后记

1 MergedBeanDefinition 后置处理

MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition是spring给我们提供的又一BeanPostProcessor扩展点,用于处理合并后的BeanDefinition(RootBeanDefinition)。

1.1 在哪里被调用执行?

在上一阶段实例化Bean,我们知道是在AbstractAutowireCapableBeanFactory的doCreateBean()方法中完成,代码如下:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// 省略实例化Object bean = instanceWrapper.getWrappedInstance();Class beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}// 省略 异常处理mbd.postProcessed = true;}}// 省略...
}

实例化之后开始执行applyMergedBeanDefinitionPostProcessors()方法,即使用MergedBeanDefinitionPostProcessor后置处理器处理合并后的BeanDefinition,方法源代码如下:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) {for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);}
}
package org.springframework.beans.factory.support;import org.springframework.beans.factory.config.BeanPostProcessor;/*** 后置处理器回调接口*/
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {/*** 处理指定beanName合并后的BeanDefinition*/void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName);/*** 重置指定beanName的BeanDefinition*/default void resetBeanDefinition(String beanName) {}}

1.2 两个常用的实现类

那么具体应该干嘛呢?我们看下它的两个重要的实现类做了什么。

1.2.1 AutowiredAnnotationBeanPostProcessor

  • AutowiredAnnotationBeanPostProcessor:自动注入注解bean后置处理器,比如@Autowired,@value

查看AutowiredAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition()方法

	@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}

findAutowiringMetadata()查找自动注入的元数据

	private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) {// Fall back to class name as cache key, for backwards compatibility with custom callers.String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());// Quick check on the concurrent map first, with minimal locking.InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);if (InjectionMetadata.needsRefresh(metadata, clazz)) {synchronized (this.injectionMetadataCache) {metadata = this.injectionMetadataCache.get(cacheKey);if (InjectionMetadata.needsRefresh(metadata, clazz)) {if (metadata != null) {metadata.clear(pvs);}metadata = buildAutowiringMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata;}

injectionMetadataCache注入元数据缓存,默认是没有当前beanName对应的自动注解元数据,继续执行buildAutowiringMetadata()方法

private InjectionMetadata buildAutowiringMetadata(Class clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;}List elements = new ArrayList<>();Class targetClass = clazz;do {final List currElements = new ArrayList<>();ReflectionUtils.doWithLocalFields(targetClass, field -> {MergedAnnotation ann = findAutowiredAnnotation(field);if (ann != null) {if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;}boolean required = determineRequiredStatus(ann);currElements.add(new AutowiredFieldElement(field, required));}});// 省略...elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}while (targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz);
}public static void doWithLocalFields(Class clazz, FieldCallback fc) {for (Field field : getDeclaredFields(clazz)) {try {fc.doWith(field);}catch (IllegalAccessException ex) {throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);}}
}@FunctionalInterface
public interface FieldCallback {/*** Perform an operation using the given field.* @param field the field to operate on*/void doWith(Field field) throws IllegalArgumentException, IllegalAccessException;
}@Nullable
private MergedAnnotation findAutowiredAnnotation(AccessibleObject ao) {MergedAnnotations annotations = MergedAnnotations.from(ao);for (Class type : this.autowiredAnnotationTypes) {MergedAnnotation annotation = annotations.get(type);if (annotation.isPresent()) {return annotation;}}return null;
}

buildAutowiringMetadata()方法实现缓存@Autowired、@Value等标注的字段、方法的流程如下

  • 创建一个大的ArrayList容器elements

  • 执行do循环

    • 创建当前存放当前类InjectionMetadata.InjectedElement的小ArrayList容器currElements

    • ReflectionUtils.doWithLocalFields()方法收集@Autowired、@Value等标注的字段、方法

      • doWithLocalFields()第二形参为FieldCallback,函数式接口,实际执行的是实参的箭头函数

      • 遍历获取目标class中Field字段,检测Field字段上注解方式包含在autowiredAnnotationTypes中。如果是把Field放入currElements集合中

        • private final Set> autowiredAnnotationTypes = new LinkedHashSet<>(4);public AutowiredAnnotationBeanPostProcessor() {this.autowiredAnnotationTypes.add(Autowired.class);this.autowiredAnnotationTypes.add(Value.class);try {this.autowiredAnnotationTypes.add((Class)ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));logger.trace("'jakarta.inject.Inject' annotation found and supported for autowiring");}catch (ClassNotFoundException ex) {// jakarta.inject API not available - simply skip.}try {this.autowiredAnnotationTypes.add((Class)ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");}catch (ClassNotFoundException ex) {// javax.inject API not available - simply skip.}}
          
        • autowiredAnnotationTypes中有我们常用的@Autowired、@Value注解

    • 遍历玩Fields,会用相同逻辑处理Methods

    • 把currElements中元素全部放入大集合elements

  • 如果父类不为Object或者null,继续循环,即会把父类中标记了对应注解的字段、方法也放入集合

AutowiredAnnotationBeanPostProcessor在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 等标注的方法、字段进行缓存

1.2.2 CommonAnnotationBeanPostProcessor

  • CommonAnnotationBeanPostProcessor:通用注解bean后置处理器,比如@Resource

CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition()方法执行和上述相同的逻辑,不同的是标记元素的注解类型:@Resource和jakarta.ejb.EJB

CommonAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Resource 等标注的字段、方法进行缓存

2 Bean 属性赋值

容器在执行完MergedBeanPostProcessors相关方法后,开始执行Bean属性赋值,具体就是执行AbstractAutowiredCapableBeanFactory类的doCreateBean()方法第603行populateBean()方法

2.1 实例化后阶段

​ populateBean()方法如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// 省略...if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}
// 省略...}

InstantiationAwareBeanPostProcessor我们在之前学习实例化前阶段的时候讲解过。实例化前阶段扩展点为该接口的 postProcessBeforeInstantiation()方法,这里实例化后阶段用到该接口的 postProcessAfterInstantiation()方法。

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;
}

postProcessAfterInstantiation()方法默认返回true;如果返回false,在populateBean()方法中,不会继续执行后续属性赋值。该方法是自定义属性注入提供一个合适的扩展点。

下面做一个小测试,看看该方法返回false会怎么样?

@Testpublic void testAfter() {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if ("person1".equals(beanName)) {return false;}return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);}});factory.registerBeanDefinition("person1",BeanDefinitionBuilder.genericBeanDefinition(Person.class).addPropertyValue("name", "张三").addPropertyValue("age", 25).getBeanDefinition());factory.registerBeanDefinition("person2",BeanDefinitionBuilder.genericBeanDefinition(Person.class).addPropertyValue("name", "李四").addPropertyValue("age", 28).getBeanDefinition());Person person1 = factory.getBean("person1", Person.class);Person person2 = factory.getBean("person2", Person.class);System.out.println(person1);System.out.println(person2);}

测试结果如下:

Person{name='null', age=null}
Person{name='李四', age=28}

2.2 Bean 属性赋值前处理

Bean属性赋值前操作,会调用InstantiationAwareBeanPostProcessor的提供的扩展点方法postProcessProperties()方法,可能会调用postProcessPropertyValues()方法。

我们先来看下populateBean()中调用逻辑,代码如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// 省略。。。PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);// 注册自动注入非简单类型依赖关系int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}// 省略。。。}

解析:

  • 在获取属性值后,会根据自动注入类型,注册非简单类型属性的依赖关系。
  • 判断是否有InstantiationAwareBeanPostProcessor实现
    • 执行接口的postProcessProperties()方法
    • 判断返回的属性值集合是否为空
      • 执行接口的破碎tProcessPropertyValues()方法
      • 判断返回属性值集合为空,直接返回

说明:

  • 如果接口的两个方法都返回空的情况下,不在执行后续的属性赋值操作

下面我们来下接口中这两个方法源代码:

@Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}@Deprecated@Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
  • 前者默认返回null,后者默认返回传入的属性值集合。即默认情况下,会继续执行后续的属性赋值。

实例代码如下:

@Testpublic void testPostProcessProperties() {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if ("person1".equals(beanName)) {if (pvs == null) {pvs = new MutablePropertyValues();}MutablePropertyValues mpvs  = (MutablePropertyValues) pvs;mpvs.addPropertyValue("name", "李四");mpvs.addPropertyValue("age", 25);return mpvs;}return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);}});factory.registerBeanDefinition("person1",BeanDefinitionBuilder.genericBeanDefinition(Person.class).addPropertyValue("name", "张三").getBeanDefinition());Person person1 = factory.getBean("person1", Person.class);System.out.println(person1);}

测试结果:

Person{name='李四', age=25}
  • 同名属性值覆盖,非同名新增。

2.3 Bean 属性赋值

Bean属性赋值,我们先看下执行逻辑,继续回到AbstractAutowireCapableBeanFactory的populateBean()方法

if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}

applyPropertyValues()完成赋值,有兴趣的可自行查阅相关文档,这里不深入讲解。

后记

如果小伙伴什么问题或者指教,欢迎交流。

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/spring6-study

参考:

[1]Spring系列之Bean生命周期详解[CP/OL]

相关内容

热门资讯

使用分享!新版WEPOKER透... 使用分享!新版WEPOKER透视挂辅助器软件是真吗”(确实是有挂)-知乎是一款可以让一直输的玩家,快...
重大发现“么么四川麻将开挂神器... 重大发现“么么四川麻将开挂神器”√外卦神器下载亲.么么四川麻将这款游戏是可以开挂的,确实是有挂的,通...
分享实测(中至南昌麻将)外挂开... 您好,中至南昌麻将这款游戏可以开挂的,确实是有挂的,通过微信【29290261】很多玩家在这款游戏中...
分享实测(众汇棋牌)外挂开挂辅... 【无需打开直接搜索微信;29290261】 操作使用教程:1.亲,实际上众汇棋牌是可以开挂的,确实有...
今日重磅消息“攒劲甘肃麻将开挂... 今日重磅消息“攒劲甘肃麻将开挂器”√详细开挂教程亲.攒劲甘肃麻将这款游戏是可以开挂的,确实是有挂的,...