Spring 源码解析CommonAnnotationBeanPostProcessor

 更新时间:2022年10月15日 10:38  点击:391 作者:Pseudocode

概述

基于 Spring Framework v5.2.6.RELEASE

前面的几篇文章,通过源码分析了 AnnotationConfigApplicationContext 初始化时注册的两个关键的后处理器 ConfigurationClassPostProcessor 和 AutowiredAnnotationBeanPostProcessor 的作用和工作原理,本文接着介绍第三个关键的后处理器 CommonAnnotationBeanPostProcessor。

以下是 Spring 上下文初始化过程中,CommonAnnotationBeanPostProcessor 被注册的代码片段。这段代码在 AnnotationConfigUtils 类的registerAnnotationConfigProcessors方法中。

registerAnnotationConfigProcessors

// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
   RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
   def.setSource(source);
   beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}

从代码的注释中可以看到,这个后处理器的作用,是为了适配 JSR-250 的特性,关于 JSR-250 是什么,会在下文中介绍。

除此之外,除了判断当前的容器是否已经注册了这个后处理器外,还有一个判断条件是jsr250Present,这个变量的初始化可以在 AnnotationConfigUtils 类中的静态代码块里找到:

jsr250Present = ClassUtils.isPresent("javax.annotation.Resource", classLoader);

其实就是看能不能加载到javax.annotation.Resource类型,如果能,则jsr250Present的值就是true。也就是说,如果能加载到javax.annotation.Resource类型,说明当前 Spring 运行的环境是支持 JSR-250 特性的,只有在这种条件下,Spring 才需要注册 CommonAnnotationBeanPostProcessor 后处理器。

说了这么多,我们有必要先了解一下 JSR-250 是什么。

JSR 和 JSR-250

JSR 是 Java Specification Requests 的缩写,意思是「Java 规范提案」,是 Java 平台重要的技术标准。JSR 由开放组织 JCP(Java Community Process)维护,任何组织成员都可以提出 JSR 提案,以向 Java 平台提供新的规范和技术,经过公开审查和 JCP 执行委员会的投票,JSR 会最终成为正式的标准。

JSR-250 的全称是 Common Annotations for the JavaTM Platform,也就是 Java 平台的公共注解。这也是本文要介绍的后处理器名字叫 CommonAnnotationBeanPostProcessor 的原因。

参考链接:The Java Community Process(SM) Program - JSRs: Java Specification Requests - detail JSR# 250

JSR-250 注解可以在javax.annotation包下找到。

我们打开其中的一个注解的源码,比如 Resource 的源码。

可以看到,注释中标记了支持该注解的 JDK 起始版本之外,还注明了起始的 Common Annotations 版本。

了解这些之后,我们回到 Spring 的源码,开始分析 CommonAnnotationBeanPostProcessor 后处理器。

CommonAnnotationBeanPostProcessor 分析

根据惯例,还是先从它的类继承关系下手。

可以看到,它是一个 BeanPostProcessor 的实现类,实现了4个 Bean 后处理器接口,并继承了 InitDestroyAnnotationBeanPostProcessor 类。

我们再看一下它实现的这些接口中,定义了哪些后处理方法。

要分析 Spring 是如何通过 CommonAnnotationBeanPostProcessor 来支持 JSR-250 特性的,就需要从这些方法下手。我们可以从 CommonAnnotationBeanPostProcessor 和它的父类 InitDestroyAnnotationBeanPostProcessor 的源码中,查找它们实现了哪些处理方法。总结如下:

CommonAnnotationBeanPostProcessor 主要在postProcessMergedBeanDefinitionpostProcessProperties方法中增加了处理逻辑。InitDestroyAnnotationBeanPostProcessor 则主要在postProcessBeforeInitializationpostProcessBeforeDestruction方法中增加了处理逻辑。

最后,再简单地介绍一下这几个后处理方法被调用的时机:

  • postProcessMergedBeanDefinition 在通过doCreateBean使用反射机制创建 Bean 实例之后调用。
  • postProcessProperties 在装配 Bean 实例的属性前对属性进行处理。
  • postProcessBeforeInitialization 在 Bean 实例的初始化方法执行前被调用。
  • postProcessBeforeDestruction 在 Bean 实例的销毁方法执行前被调用。

Spring 主要对@Resource@PostConstruct@PreDestroy三个 JSR-250 注解提供了支持,其实根据三个注解的名称,和以上介绍的几个后处理方法被调用的时机,就能知道它们的对应关系。具体的工作原理,我们放到之后的文章中介绍。

总结

本文介绍了 CommonAnnotationBeanPostProcessor 后处理器的作用、它主要实现的后处理方法,还顺便介绍了 JSR 和 JSR-250 是什么。之后的文章,将深入分析这几个后处理器方法分别做了哪些工作,更多关于Spring CommonAnnotationBeanPostProcessor的资料请关注猪先飞其它相关文章!

原文出处:https://juejin.cn/post/7153096979092865038

[!--infotagslink--]

相关文章

  • Spring AOP 对象内部方法间的嵌套调用方式

    这篇文章主要介绍了Spring AOP 对象内部方法间的嵌套调用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-29
  • Spring Cloud 中@FeignClient注解中的contextId属性详解

    这篇文章主要介绍了Spring Cloud 中@FeignClient注解中的contextId属性详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-25
  • Springboot如何实现Web系统License授权认证

    这篇文章主要介绍了Springboot如何实现Web系统License授权认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-05-28
  • 如何在Spring WebFlux的任何地方获取Request对象

    这篇文章主要介绍了如何在Spring WebFlux的任何地方获取Request对象,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下...2021-01-26
  • 详解SpringCloudGateway内存泄漏问题

    这篇文章主要介绍了详解SpringCloudGateway内存泄漏问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-07-16
  • Spring为什么不推荐使用@Autowired注解详析

    @Autowired 注解的主要功能就是完成自动注入,使用也非常简单,但这篇文章主要给大家介绍了关于Spring为什么不推荐使用@Autowired注解的相关资料,需要的朋友可以参考下...2021-11-03
  • Springboot如何使用mybatis实现拦截SQL分页

    这篇文章主要介绍了Springboot使用mybatis实现拦截SQL分页,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-19
  • SpringMVC文件上传原理及实现过程解析

    这篇文章主要介绍了SpringMVC文件上传原理及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-15
  • Spring Data JPA 关键字Exists的用法说明

    这篇文章主要介绍了Spring Data JPA 关键字Exists的用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-10
  • tomcat启动完成执行 某个方法 定时任务(Spring)操作

    这篇文章主要介绍了tomcat启动完成执行 某个方法 定时任务(Spring)操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-25
  • 使用Maven 搭建 Spring MVC 本地部署Tomcat的详细教程

    这篇文章主要介绍了使用Maven 搭建 Spring MVC 本地部署Tomcat,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-08-16
  • Java Spring Cloud 负载均衡详解

    这篇文章主要介绍了Spring Cloud负载均衡及远程调用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2021-09-18
  • SpringMvc自动装箱及GET请求参数原理解析

    这篇文章主要介绍了SpringMvc自动装箱及GET请求参数原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-19
  • Springboot使用thymeleaf动态模板实现刷新

    这篇文章主要介绍了Springboot使用thymeleaf动态模板实现刷新,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-08-31
  • SpringMvc获取请求头请求体消息过程解析

    这篇文章主要介绍了SpringMvc获取请求头请求体消息过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-17
  • Idea打包springboot项目没有.original文件解决方案

    这篇文章主要介绍了Idea打包springboot项目没有.original文件解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-26
  • spring boot 使用utf8mb4的操作

    这篇文章主要介绍了spring boot 使用utf8mb4的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-20
  • Springmvc ResponseBody响应json数据实现过程

    这篇文章主要介绍了Springmvc ResponseBody响应json数据实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-10-26
  • SpringData Repository接口用法解析

    这篇文章主要介绍了SpringData Repository接口用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-08-27
  • Spring MVC 处理一个请求的流程

    Spring MVC是Spring系列框架中使用频率最高的部分。不管是Spring Boot还是传统的Spring项目,只要是Web项目都会使用到Spring MVC部分。因此程序员一定要熟练掌握MVC部分。本篇博客简要分析Spring MVC处理一个请求的流程。...2021-02-06