初识Spring源码 -- applyMergedBeanDefinitionPostProcessors

Posted 做猪呢,最重要的是开森啦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识Spring源码 -- applyMergedBeanDefinitionPostProcessors相关的知识,希望对你有一定的参考价值。

0. 举个栗子:

 本版本源码为SpringBoot - 2.3.3.RELEASE,即spring-beans: 5.2.8.RELEASE
·
 主要通过学习@Autowired注入过程来学习Bean创建生命周期
·
 主要源码入口:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

@Component
public class SetterBean {

    @Autowired
    private BeanService beanService;
    
}

@Configuration
public class ConfigurationBean {
    @Bean
    public BeanService beanService() {
        BeanServiceImpl beanService = new BeanServiceImpl();
        beanService.setName("zhangsan");
        return beanService;
    }
}

 在createBeanInstance创建bean实例后(该方法简要可参考createBeanInstance基本功能
·
 会应用applyMergedBeanDefinitionPostProcessors这个后置处理器,去收集/预解析属性元数据

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
		
	... ... ... ...
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	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);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}
	... ... ... ...
}

1. applyMergedBeanDefinitionPostProcessors:

 这个方法本质就是调用MergedBeanDefinitionPostProcessor接口实现类的postProcessMergedBeanDefinition方法
·
 通过该方法去收集类中指定注解的属性元数据,这里主要分析AutowiredAnnotationBeanPostProcessor

  • AutowiredAnnotationBeanPostProcessor 支持@Autowired,@Value注解
  • CommonAnnotationBeanPostProcessor 支持@PostConstruct,@PreDestroy,@Resource注解
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);
		}
	}
}

 1.1. AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:

 主要通过findAutowiringMetadata方法去收集@Autowired,@Value注解的属性元数据

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}
  1.1.1. findAutowiringMetadata:

 先从缓存中查找有没有要注入的属性元数据对象InjectionMetadata,有则直接返回
 缓存没有,则经过双重校验后,去构建要注入属性的元数据;构建成功写入缓存

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// 先从缓存中查找有没有要注入的属性元数据,有则直接返回
	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;
}
  1.1.2. buildAutowiringMetadata:

 通过循环遍历类属性和方法,查找出指定注解注释的属性和方法,
 属性封装到AutowiredFieldElement,方法封装到AutowiredMethodElement,最后都封装到InjectionMetadata返回

private InjectionMetadata buildAutowiringMetadata(final 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 -> {
			// 循环遍历类属性,找到@Autowired,@Value注解的属性
			MergedAnnotation<?> ann = findAutowiredAnnotation(field);
			if (ann != null) {
				// 判断该属性是否是static修饰的,是的话则直接返回,可能导致该属性后续无法注入
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				// 判断属性是否是必须的,除非显示指定非必须@Autowired(required = false),默认是true
				boolean required = determineRequiredStatus(ann);
				// 找到指定注解的属性,封装成AutowiredFieldElement,然后添加到currElements
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});

		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			// 循环遍历类方法,找到@Autowired,@Value注解的方法
			MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				// 判断该方法是否是static修饰的,是的话则直接返回
				if (Modifier.isStatic(method.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static methods: " + method);
					}
					return;
				}
				if (method.getParameterCount() == 0) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation should only be used on methods with parameters: " +
								method);
					}
				}
				// 判断方法是否是必须的,除非显示指定非必须@Autowired(required = false),默认是true
				boolean required = determineRequiredStatus(ann);
				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
				// 找到指定注解的方法,封装成AutowiredMethodElement,然后添加到currElements
				currElements.add(new AutowiredMethodElement(method, required, pd));
			}
		});

		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);

	return InjectionMetadata.forElements(elements, clazz);
}
  1.1.3. ReflectionUtils#doWithLocalFields:

 和doWithLocalMethods方法一样,第二个参数是函数式接口

  • 循环遍历类属性,执行fc.doWith(field);,会触发回调函数方法
  • 在findAutowiredAnnotation方法查找该属性,是否被@Autowired,@Value注解

 这类函数式接口回调,在spring源码中很常见,也是很妙(doge)

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);
		}
	}
}
  1.1.4. populateBean:

 收集完的属性,会在属性填充方法populateBean里面进行依赖注入,本方法代码后续再详细介绍

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		... ... ...
		try {
			populateBean(beanName, mbd, instanceWrapper);
		... ... ...

 通过AutowiredAnnotationBeanPostProcessor#postProcessProperties方法,进行属性注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	... ... ...
	boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
	boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// 新版本调用postProcessProperties来进行依赖注入
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					// 兼容旧版本使用postProcessPropertyValues依赖注入
					pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
	}
	... ... ...

 上述applyMergedBeanDefinitionPostProcessors中已经完成属性元数据的预解析,所以能直接获取封装好的属性元数据数据

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	// 获取类中封装好的属性元数据数据
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
	try {
		metadata.inject(bean, beanName, pvs);
	}
	catch (BeanCreationException ex) {
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
	}
	return pvs;
}

 关于属性填充和注入的详情,可查看文章:属性填充populateBean | 静态属性注入

  1.1.5. 小结:

 在createBeanInstance创建bean实例后(该方法简要可参考createBeanInstance基本功能
·
 会应用applyMergedBeanDefinitionPostProcessors这个后置处理器,去收集/预解析属性元数据
·
 通过循环遍历类属性和方法,找到有指定注解的属性,封装到注入元数据对象InjectionMetadata
·
 在属性填充populateBean时,从缓存中获取InjectionMetadata,进行注入

 1.2. CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition:

 改方法会收集@PostConstruct 、@Resource的元数据信息

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	// 调用父类方法收集@PostConstruct元数据信息
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	// 通过findResourceMetadata方法去收集@Resource注解的属性元数据
	InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}
  1.2.1. findResourceMetadata:
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
	String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
	// 先从缓存中查找有没有要注入的属性元数据,有则直接返回
	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);
				}
				// 经过双重校验后,去构建标注@Resource属性的元数据
				metadata = buildResourceMetadata(clazz);
				// 构建完写入缓存,方便调用获取,防止重复解析
				this.injectionMetadataCache.put(cacheKey, metadata);
			}
		}
	}
	return metadata;
}
  1.2.2. buildResourceMetadata:

 通过循环遍历类属性和方法,查找出@Resource注解注释的属性和方法,
 都属性封装到ResourceElement,最后都封装到InjectionMetadata返回

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
	if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
		return InjectionMetadata.EMPTY;
	}

	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
	Class<?> targetClass = clazz;

	do {
		final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

		ReflectionUtils.doWithLocalFields(ta

以上是关于初识Spring源码 -- applyMergedBeanDefinitionPostProcessors的主要内容,如果未能解决你的问题,请参考以下文章

初识Spring源码 -- applyMergedBeanDefinitionPostProcessors

初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource

初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource

初识Spring源码 -- 属性填充populateBean | 静态属性注入

初识Spring源码 -- 属性填充populateBean | 静态属性注入

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段