spring注入点元数据的缓存
在分析spring生命周期中属性注入方法前。有必要分析第三次后置处理器方法
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
示例代码
package com.populate;
@Component
public class B {
}
package com.populate;
@Component
public class A implements InitializingBean {
@Autowired
B b;
@Autowired
public void myMethod(){
System.out.println("myMethod");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean");
}
@PostConstruct
public void postConstru(){
System.out.println("postConstru");
}
}
package com;
@Configuration
@ComponentScan("com.populate")
public class AppConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext( AppConfig.class );
A a = ac.getBean( A.class );
System.out.println( a );
缓存注入点信息
调用applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
debug分析调用链
doCreateBean
在第二次后置处理器,通过推测构造方法创建bean对象之后(属性值是null)
AbstractAutowireCapableBeanFactory#doCreateBean
![](https://img.haomeiwen.com/i7310356/30da356284d1770d.png)
applyMergedBeanDefinitionPostProcessors
AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
在这个方法内,将会遍历所有BeanPostProcessors(Bean后置处理器,扩展点之一):
1、ApplicationContextAwareProcessor
2、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
3、PostProcessorRegistrationDelegate$BeanPostProcessorChecker
4、CommonAnnotationBeanPostProcessor
5、AutowiredAnnotationBeanPostProcessor
6、RequiredAnnotationBeanPostProcessor
7、ApplicationListenerDetector
对于属于MergedBeanDefinitionPostProcessor类(4、5、6、7)的调用postProcessMergedBeanDefinition方法
首先看CommonAnnotationBeanPostProcessor调用分析
![](https://img.haomeiwen.com/i7310356/43317e475a44c7bc.png)
postProcessMergedBeanDefinition
CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
首先调用父类查找findLifecycleMetadata(生命周期元数据)、findResourceMetadata(Resource注解元数据)、checkConfigMembers配置信息成员检查
![](https://img.haomeiwen.com/i7310356/893ddb4c131310d4.png)
![](https://img.haomeiwen.com/i7310356/c2787e55a24963f9.png)
父类postProcessMergedBeanDefinition
InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
生命周期元数据查找、配置信息成员检查
![](https://img.haomeiwen.com/i7310356/d45fe5ffcaf3519e.png)
findLifecycleMetadata
InitDestroyAnnotationBeanPostProcessor#findLifecycleMetadata
首先从lifecycleMetadataCache缓存查找,第一次肯定为null。经过多线程双重检查查找并构建。
![](https://img.haomeiwen.com/i7310356/adb9cb7b7471765a.png)
buildLifecycleMetadata
InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata
initAnnotationType表示PostConstruct注解,destroyAnnotationType表示PreDestroy注解
这里会通过lambda处理。查找是否有加了PostConstruct,PreDestroy注解的方法。最后创建LifecycleMetadata对象并返回。
结果放到lifecycleMetadataCache缓存中
![](https://img.haomeiwen.com/i7310356/d687dcfeb27408ca.png)
![](https://img.haomeiwen.com/i7310356/ec7f1fe88d8e3e14.png)
利用lambda表达式进行处理,简单说明下调用过程
首先看ReflectionUtils#doWithLocalMethods方法里面是什么
public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
Method[] methods = getDeclaredMethods(clazz);
for (Method method : methods) {
try {
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
}
ReflectionUtils.MethodCallback里面是什么
public interface MethodCallback {
void doWith(Method method) throws IllegalArgumentException, IllegalAccessException;
}
当调用到ReflectionUtils.doWithLocalMethods方法将会进入方法内,调用getDeclaredMethods会得到方法集合通过遍历methods ,调用mc.doWith(method)方法,之后便会调用到method->表达式。
为什么是这样的调用流程:可以简单的这样理解,doWithLocalMethods方法有两个参数Class、
MethodCallback。MethodCallback接口只有一个方法。所以这个lambda表达式{}就是doWith方法实现,method就是mc.doWith(method)中的参数method。doWithLocalMethods如果没有MethodCallback参数,lambda表达式可以替换mc.doWith(method)的实现
checkConfigMembers
LifecycleMetadata#checkConfigMembers
![](https://img.haomeiwen.com/i7310356/31c5ecbc7202bd00.png)
首先通过isExternallyManagedInitMethod方法查看externallyManagedInitMethods集合中是否存在initMethod
public boolean isExternallyManagedInitMethod(String initMethod) {
synchronized (this.postProcessingLock) {
return (this.externallyManagedInitMethods != null &&
this.externallyManagedInitMethods.contains(initMethod));
}
}
RootBeanDefinition#registerExternallyManagedInitMethod
注册到RootBeanDefinition的externallyManagedInitMethods集合,最后也添加到当前对象的checkedInitMethods和checkedDestroyMethods集合中
![](https://img.haomeiwen.com/i7310356/28508e1d9d82f2a1.png)
![](https://img.haomeiwen.com/i7310356/03760d1c157e500b.png)
调用父类postProcessMergedBeanDefinition结束
findResourceMetadata
调用类似的过程,查找注入点Field和Method是否有Resource注解。构建InjectionMetadata对象返回,并放到injectionMetadataCache缓存。然后进行InjectionMetadata#checkConfigMembers方法,检查赋值等操作
CommonAnnotationBeanPostProcessor#findResourceMetadata
![](https://img.haomeiwen.com/i7310356/ff9999e6998f80da.png)
CommonAnnotationBeanPostProcessor#buildResourceMetadata
![](https://img.haomeiwen.com/i7310356/2d0128bc85112256.png)
AutowiredAnnotationBeanPostProcessor调用分析
postProcessMergedBeanDefinition
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
![](https://img.haomeiwen.com/i7310356/817a1cc751e66f49.png)
findAutowiringMetadata
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
![](https://img.haomeiwen.com/i7310356/77542d6739f02d9f.png)
buildAutowiringMetadata
AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
![](https://img.haomeiwen.com/i7310356/eee00fa73b8c784b.png)
![](https://img.haomeiwen.com/i7310356/cdf48b96ee5d92e3.png)
findAutowiredAnnotation
AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation
autowiredAnnotationTypes包含的注解值有Autowired、Value
![](https://img.haomeiwen.com/i7310356/de4bc643f448730f.png)
![](https://img.haomeiwen.com/i7310356/2418eff5e0105842.png)
如果方法是isStatic将会返回,报错不支持静态方法并返回
找到后构建InjectionMetadata对象返回并放到AutowiredAnnotationBeanPostProcessor#injectionMetadataCache集合
checkConfigMembers
org.springframework.beans.factory.annotation.InjectionMetadata#checkConfigMembers
从InjectionMetadata对象的injectedElements集合中遍历,放到beanDefinition的externallyManagedConfigMembers集合,之后放到checkedElements集合
![](https://img.haomeiwen.com/i7310356/47191caba70989f7.png)
总结:
本章主要讨论创建bean的过程中第三次后置处理器方法,对于注入点元数据的缓存。
注入点元数据(这里1、2注入点元数据缓存,3在推测构造方法创建已经处理)
1、field属性
2、method方法
3、constructor构造方法
方法对bean后置处理器遍历并进行方法调用
主要有两个后置处理器
1、CommonAnnotationBeanPostProcessor @Resource
2、AutowiredAnnotationBeanPostProcessor @Autowired