我们在之前的文章分析里已经知道AnnotationConfigServletWebServerApplicationContext在初始化时会实例化一些后置处理器,其中就包括CommonAnnotationBeanPostProcessor处理器,通过之前我们分析@Autowired注解解析流程知道比较关键的两个流程是通过MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()对需要处理的注解进行解析并封装成InjectionMetadata,然后通过InstantiationAwareBeanPostProcessor.postProcessProperties()方法对InjectionMetadata进行处理,把相应的对象或value找到并填充到属性中。而CommonAnnotationBeanPostProcessor
跟AutowiredAnnotationBeanPostProcessor继承体系是一样的,流程也差不多,只是在处理细节上稍微有一些区别。
CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition方法
首先调了父类的postProcessMergedBeanDefinition方法,而他的父类是InitDestroyAnnotationBeanPostProcessor,所以先看父类的实现逻辑:
InitDestroyAnnotationBeanPostProcessor.InitDestroyAnnotationBeanPostProcessor方法
代码结构几乎是一样的,那么我们重点关注的是InitDestroyAnnotationBeanPostProcessor处理的是哪些注解以及在什么时候开始注解逻辑。
调用细节这里就不多说了,跟@Autowired流程一样,从buildLifecycleMetadata方法可以看出:主要是解析initAnnotationType和destroyAnnotationType两个注解,然后封装成LifecycleElement和LifecycleMetadata,需要注意的是被修饰的方法必须是无参方法,那么initAnnotationType和destroyAnnotationType具体代表是哪两个注解呢
initAnnotationType和destroyAnnotationType具体代表是哪两个注解呢
从CommonAnnotationBeanPostProcessor的构造方法可以看出,initAnnotationType就是@PostConstruct注解,destroyAnnotationType就是@PreDestroy注解。initAnnotationType和destroyAnnotationType这两个注解的含义以及被这两个注解的解析过程已经了解了,那么什么时候对封装后的LifecycleElement和LifecycleMetadata进行处理呢?
LifecycleElement和LifecycleMetadata处理入口以及流程这个流程就要回到bean的实例化流程里:通过doCreateBean方法对bean实例化时会先用无参构造器或工厂方法进行实例化类,然后用populateBean方法对实例化对象进行属性的填充,填充完之后用initializeBean方法对bean实例化时需要调用的一些初始化方法进行最后的调用,然后就算实例化完成了,在就注册了一些bean销毁时调用的后置处理器(DestructionAwareBeanPostProcessor)。而我们的@PostConstruct就是在initializeBean方法中处理,@PreDestroy在bean销毁时DestructionAwareBeanPostProcessor.postProcessBeforeDestruction方法中处理。
initializeBean方法处理@PostConstruct
- 对BeanNameAware、BeanClassLoaderAware、BeanFactoryAware中的方法进行调用
- 调用BeanPostProcessor.postProcessBeforeInitialization()方法
- 调用InitializingBean.afterPropertiesSet()方法和bean的自定义init方法
- 调用BeanPostProcessor.postProcessAfterInitialization()方法
而我们的@PostConstruct就是在BeanPostProcessor.postProcessBeforeInitialization()方法中被处理。
InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization()方法
可以看到实际上就是使用了反射调用了@PostConstruct修饰的方法。
InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction()方法
可以看到实际上就是使用了反射调用了@PreDestroy修饰的方法。
至此,InitDestroyAnnotationBeanPostProcessor对于@PostConstruct和@PreDestroy的处理逻辑就处理完了。我们接着看CommonAnnotationBeanPostProcessor中的postProcessMergedBeanDefinition()逻辑。
CommonAnnotationBeanPostProcessor.findResourceMetadata方法
resourceAnnotationTypes这个属性是使用下面这个static代码块初始化的
而@Resource注解会被封装成ResourceElement对象。
ResourceElement.getResourceToInject方法
可以看到@Resource默认是name进行注入,如果@Resource设置了name则以设置的为准否则以属性的变量名为准。
总结:- CommonAnnotationBeanPostProcessor实际上处理了@PostConstruct、@PreDestroy和@Resource注解,但@PostConstruct、@PreDestroy是交给父类DestructionAwareBeanPostProcessor来处理。
- @PostConstruct是在bean已经实例化且属性也已经填充完后在initializeBean方法中进行处理,@PostConstruct在bean被销毁时处理
- @Resource注入时是按name来注入,name优先取@Resource中的name否则取变量名。而@Autowired默认是按classType注入,当找到多个classType类时按变量名注入。