初识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注入(代码片段