0106MergedBeanDefinition处理和Bean属性赋值-Bean生命周期详解-spring

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]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值