文章目录
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()方法
@Override
public 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<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<InjectionMetadata.InjectedElement> 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<Class<? extends Annotation>> 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 等标注的方法、字段进行缓存
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会怎么样?
@Test
public void testAfter() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
@Override
public 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()方法
- 判断返回属性值集合为空,直接返回
说明:
- 如果接口的两个方法都返回空的情况下,不在执行后续的属性赋值操作
下面我们来下接口中这两个方法源代码:
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
- 前者默认返回null,后者默认返回传入的属性值集合。即默认情况下,会继续执行后续的属性赋值。
实例代码如下:
@Test
public void testPostProcessProperties() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
@Override
public 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]