MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition是spring给我们提供的又一BeanPostProcessor扩展点,用于处理合并后的BeanDefinition(RootBeanDefinition)。
在上一阶段实例化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) {}}
那么具体应该干嘛呢?我们看下它的两个重要的实现类做了什么。
查看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 extends Annotation> 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 extends Annotation>)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 extends Annotation>)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 等标注的方法、字段进行缓存
CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition()方法执行和上述相同的逻辑,不同的是标记元素的注解类型:@Resource和jakarta.ejb.EJB
CommonAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Resource 等标注的字段、方法进行缓存
容器在执行完MergedBeanPostProcessors相关方法后,开始执行Bean属性赋值,具体就是执行AbstractAutowiredCapableBeanFactory类的doCreateBean()方法第603行populateBean()方法
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}
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;}}// 省略。。。}
解析:
说明:
下面我们来下接口中这两个方法源代码:
@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;}
实例代码如下:
@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}
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]