SpringBoot自动装配 源码解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: SpringBoot自动装配 源码解析

SpringBoot 版本 : 2.2.1.RELEASE
关键词:@EnableAutoConfiguration,/META-INF/spring.factories,/META-INF/spring-autoconfigure-metadata.properties
注:本文主要讲解一些比较重要的关键步骤,不能面面俱到,若有疑问,随时保持沟通

大家都知道,SpringBoot 六大特性:

  • 创建独立的Spring应用
  • 嵌入式Web容器(可以以可执行jar方式运行,不需要部署WAR文件)
  • 提供固化的 "starter",简化构建配置
  • 当条件满足时自动地装配Spring或第三方库
  • 提供运维特性(Production-Ready)特性,如指标信息(Metrics)、健康检查、外部化配置。
  • 不需要XML配置
  • 其中有一项为自动装配功能,自动装配功能总体来说由 @EnableXXX注解 + @Import , 再配合@Conditional注解可以实现条件自动装配,在SpringBoot中核心注解为@EnableAutoConfiguration

1. @EnableAutoConfiguration注解

  • 通常情况下,springBoot应用启动类不会直接标注此注解,而是通过@SpringBootApplication注解来实现:image.png发现 @SpringBootApplication中包含了 @SpringBootConfiguration(等同于@Configuration)、@EnableAutoConfiguration、@ComponentScan 注解。

总结:在启动类上加上 @EnableAutoConfiguration 注解 或者@SpringBootApplication即可实现自动装配,推荐使用 @SpringBootApplication这个组合注解。

2. @EnableAutoConfiguration注解实现自动装配原理

  • 依照 @EnableXXX的驱动设计,@EnableAutoConfiguration 必然也是按照 @Import 配合 ImportSelector或者 ImportBeandefinetionRegistrar 接口编程的套路,查看@EnableAutoConfiguration注解源码:image.png,果不其然,再进一步验证:image.png,不知读者是否还记得作者之前写过的 SpringBoot启动 源码深度解析(三)里面会有@Import注解的详细解析过程及 DeferredImportSelector 与 ImportSelector的回调逻辑。
  • 此时相信读者已经知道大致的脉络了,那么我们就重点分析一下 AutoConfigurationImportSelector 这个 ImportSelector实现。
  • 正常情况下,若类实现了 ImportSelector接口,则会回调其相对于的 selectImports方法,但是我们通类的关系图发现AutoConfigurationImportSelector 直接实现的是 DeferredImportSelector,而这个 ImportSelector 如下: image.png 是在Spring 4.0之后新增的延迟ImportSelector,且处理逻辑跟普通的 ImportSelector不同的是当前接口新定义了 Group的概念。image.png 追踪 process方法如下:image.pngimage.png重点在于此处的 grouping.getImports(),我们发现是 ConfigurationClassParser的内部静态类 DeferredImportSelectorGrouping: image.png此类中的两个处理方法正正是关键的步骤,而这两个方法正是 DeferredImportSelector 中的内部接口 Group的实现去执行的然后我们发现Group的方法默认实现是AutoConfigurationImportSelector的内部静态类AutoConfigurationGroup,如下:image.png,👍👍看到这里,读者要是对这些类的名称记得不是很清晰的话,这一段的说明我建议跟着作者的思路,在本地源码找到对应的位置 "递归以上描述",肯定会恍然大悟,若是熟悉的话可以直接跳过👍👍,然后分析:
  1. getAutoConfigurationMetadata()

image.png

image.pngimage.png

  • SprinBoot框架层帮忙做的自动装配元数据
  1. AutoConfigurationEntry entry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata)

image.png

  • AnnotationAttributes attributes = getAttributes(annotationMetadata) 获取@EnableAutoConfiguration标注类的元信息。
  • List configurations = getCandidateConfigurations(annotationMetadata, attributes):由于返回的结果是候选类的集合,跟踪调用链会发现:image.pngimage.png
    返回的是 key = org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的values值,这些values即是SpringBoot默认的自动装配类,所以有时候读者阅读源码时,发现某些类莫名其妙的被装载到Spring容器中了,一部分原因可能是这个地方搞的鬼。
  1. configurations = removeDuplicates(configurations)
  • 移除重复定义的配置类( 利用set集合的不可重复性 )
  1. Set exclusions = getExclusions(annotationMetadata, attributes)
  • 获取排除类名单,排除类可通过 exclude = {A.class.B.class}属性来排除指定的配置类。
  1. configurations = filter(configurations, autoConfigurationMetadata)
  • 经过去重和排除过的配置类再执行过滤操作,过滤代码:image.png
  • ①中 调用的是 SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader),也是在spring.factories中获取 AutoConfigurationImportFilter类型的过滤器,此处默认有image.png
  • ②中 分别执行配置类的match方法,由于 OnBeanCondition、OnClassCondition、OnWebApplicationCondition 均继承自 FilteringSpringBootCondition,match方法如下:image.pngimage.png
  • 通过上面三个子类的方法实现 ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata),此处拿OnBeanCondition类来分析image.png自动装配类集合迭代调用 autoConfigurationMetadata.getSet(autoConfigurationClass, "ConditionalOnBean")方法获取 配置类.ConditionalOnBean的元信息,即在元数据配置文件中的 values。image.png
    以 RedisCacheConfiguration为例,其 "conditionOnBean" 如下:image.png,获取返回的values值后,再调用 getOutcome()方法计算匹配结果,最终判断是由 image.png ClassNameFilter.MISSING#matches决定的。
  • 解析到这里,自动装配的底层实现细节基本已经说完了,底层实现稍微有点晦涩难懂,但是只要掌握关键性的类及注解的作用之后,再去了解源码基本上就可以手到擒来了。
总结:自动装配的流程
  • 添加 @SpringBootApplication 注解或者 @EnableAutoConfiguration
  • 通过 SpringFactoriesLoader.loadFactoryNames(...) 获取自动装配类,执行一系列的去重、排除等操作,然后通过过滤,通过判断当前类加载器是否是加载元数据的类加载器来决定 @ConditiionOnXXX 注解的装配过程。
  • 自动装配是SpringBoot的元数据配置文件(spring-autoconfigure-metadata.properties)中的配置类的选择性加载的过程。
  1. ☛ 文章要是勘误或者知识点说的不正确,欢迎评论,毕竟这也是作者通过阅读源码获得的知识,难免会有疏忽!
  2. 要是感觉文章对你有所帮助,不妨点个关注,或者移驾看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中。
  3. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处!
目录
相关文章
|
2天前
|
前端开发 Java
表白墙/留言墙 —— 初级SpringBoot项目,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
文章通过一个表白墙/留言墙的初级SpringBoot项目实例,详细讲解了如何进行前后端开发,包括定义前后端交互接口、创建SpringBoot项目、编写前端页面、后端代码逻辑及实体类封装的全过程。
12 3
表白墙/留言墙 —— 初级SpringBoot项目,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
2天前
|
缓存 Java Spring
servlet和SpringBoot两种方式分别获取Cookie和Session方式比较(带源码) —— 图文并茂 两种方式获取Header
文章比较了在Servlet和Spring Boot中获取Cookie、Session和Header的方法,并提供了相应的代码实例,展示了两种方式在实际应用中的异同。
11 3
servlet和SpringBoot两种方式分别获取Cookie和Session方式比较(带源码) —— 图文并茂 两种方式获取Header
|
2天前
|
前端开发 Java 数据安全/隐私保护
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
文章通过一个简单的SpringBoot项目,详细介绍了前后端如何实现用户登录功能,包括前端登录页面的创建、后端登录逻辑的处理、使用session验证用户身份以及获取已登录用户信息的方法。
26 2
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
|
2天前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
7 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
2天前
|
存储 JSON 算法
JWT令牌基础教程 全方位带你剖析JWT令牌,在Springboot中使用JWT技术体系,完成拦截器的实现 Interceptor (后附源码)
文章介绍了JWT令牌的基础教程,包括其应用场景、组成部分、生成和校验方法,并在Springboot中使用JWT技术体系完成拦截器的实现。
6 0
JWT令牌基础教程 全方位带你剖析JWT令牌,在Springboot中使用JWT技术体系,完成拦截器的实现 Interceptor (后附源码)
|
2天前
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
13天前
|
存储 缓存 Java
在Spring Boot中使用缓存的技术解析
通过利用Spring Boot中的缓存支持,开发者可以轻松地实现高效和可扩展的缓存策略,进而提升应用的性能和用户体验。Spring Boot的声明式缓存抽象和对多种缓存技术的支持,使得集成和使用缓存变得前所未有的简单。无论是在开发新应用还是优化现有应用,合理地使用缓存都是提高性能的有效手段。
15 1
|
2月前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
2月前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
60 6
|
27天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理

推荐镜像

更多