头秃了,Spring Boot 自动配置源码解析~

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 前言源码版本@SpringBootApplication干了什么?@EnableAutoConfiguration干了什么?总结

前言

为什么Spring Boot这么火?因为便捷,开箱即用,但是你思考过为什么会这么便捷吗?传统的SSM架构配置文件至少要写半天,而使用Spring Boot之后只需要引入一个starter之后就能直接使用,why???

原因很简单,每个starter内部做了工作,比如Mybatis的启动器默认内置了可用的SqlSessionFactory

至于如何内置的?Spring Boot 又是如何使其生效的?这篇文章就从源码角度介绍一下Spring Boot的自动配置原理。

源码版本

作者Spring Boot是基于2.4.0。每个版本有些变化,读者尽量和我保持一致,以防源码有些出入。

@SpringBootApplication干了什么?

这么说吧,这个注解什么也没做,废物,活都交给属下做了,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}

上方标注了三个重要的注解,如下:

  1. @SpringBootConfiguration:其实就是@Configuration,因此主启动类可以当做配置类使用,比如注入Bean等。
  2. @EnableAutoConfiguration:这个注解牛批了,名字就不一样,开启自动配置,哦,关键都在这了.....
  3. @ComponentScan:包扫描注解。

经过以上的分析,最终定位了一个注解@EnableAutoConfiguration,顾名思义,肯定和自动配置有关,要重点分析下。

@EnableAutoConfiguration干了什么?

想要知道做了什么肯定需要看源码,如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

上方标注了两个重要的注解,如下:

  1. @AutoConfigurationPackage:自动配置包注解,默认将主配置类(@SpringBootApplication)所在的包及其子包里面的所有组件扫描到IOC容器中。
  2. @Import:该注解不必多说了,前面文章说过很多次了,这里是导入了AutoConfigurationImportSelector,用来注入自动配置类。

以上只是简单的分析了两个注解,下面将会从源码详细的介绍一下。

@AutoConfigurationPackage

这个注解干了什么?这个需要看下源码,如下;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

重要的还是@Import注解,导入了AutoConfigurationPackages.Registrar,这个类是干什么的?源码如下图:

其实就两个方法,但是的最重要的就是registerBeanDefinitions方法,但是这个方法不用看,肯定是注入Bean,这里的重点是注入哪些Bean,重点源码如下:

//获取扫描的包
new PackageImports(metadata).getPackageNames().toArray(new String[0])

跟进代码,主要逻辑都在#PackageImports.PackageImports()这个构造方法中,源码解析如下图:

从上面源码分析可以知道,这里扫描的包名是由两部分组成,分别如下:

  1. @AutoConfigurationPackage注解中的两个属性解析得来的包名。
  2. 注解AutoConfigurationPackage所在的包名,即是@SpringBootApplication所在的包名。

@AutoConfigurationPackage默认将主配置类(@SpringBootApplication)所在的包及其子包里面的所有组件扫描到IOC容器中。

@Import(AutoConfigurationImportSelector.class)

这个注解不用多说了,最重要的就是AutoConfigurationImportSelector,我们来看看它的继承关系,如下图:

这个类的继承关系还是挺简单的,实现了Spring中的xxAware注入一些必要的组件,但是最值得关心的是实现了一个DeferredImportSelector这个接口,这个接口扩展了ImportSelector,也改变了其运行的方式,这个在后面章节会介绍。

「注意」:这个类会导致一个误区,平时看到xxxSelector已经有了反射弧了,肯定会在selectImports()方法上DEBUG,但是这个类压根就没执行该方法,我第一次看也有点怀疑人生了,原来它走的是DeferredImportSelector的接口方法。

其实该类真正实现逻辑的方法是process()方法,但是主要加载自动配置类的任务交给了getAutoConfigurationEntry()方法,具体的逻辑如下图:

上图的逻辑很简单,先从spring.factories文件中获取自动配置类,在去掉@SpringBootApplication中定义排除的自动配置类。

上图中的第步就是从META-INF/spring.factories中加载自动配置类,代码很简单,在上一篇分析启动流程的时候也有很多组件是从spring.facotries文件中加载的,代码都类似。

springboot-autoconfigure中的spring.facotries文件内置了很多自动配置类,如下:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
................

了解了Spring Boot 如何加载自动配置类,那么自定义一个自动配置类也是很简单了,后续章节教你如何定制自己的自动配置类,里面还是有很多门道的.....

总结

本文从源码角度分析了Spring Boot的自动配置是如何加载的,其实分析起来很简单,希望作者的这篇文章能帮助你更深层次的了解Spring Boot

相关文章
|
1天前
|
JavaScript Java Maven
毕设项目&课程设计&毕设项目:springboot+vue实现的在线求职管理平台(含教程&源码&数据库数据)
本文介绍了一款基于Spring Boot和Vue.js实现的在线求职平台。该平台采用了前后端分离的架构,使用Spring Boot作为后端服务
毕设项目&课程设计&毕设项目:springboot+vue实现的在线求职管理平台(含教程&源码&数据库数据)
|
1天前
|
NoSQL JavaScript 前端开发
SpringBoot+Vue实现校园二手系统。前后端分离技术【完整功能介绍+实现详情+源码】
文章介绍了如何使用SpringBoot和Vue实现一个校园二手系统,采用前后端分离技术。系统具备完整的功能,包括客户端和管理员端的界面设计、个人信息管理、商品浏览和交易、订单处理、公告发布等。技术栈包括Vue框架、ElementUI、SpringBoot、Mybatis-plus和Redis。文章还提供了部分源代码,展示了前后端的请求接口和Redis验证码功能实现,以及系统重构和模块化设计的一些思考。
SpringBoot+Vue实现校园二手系统。前后端分离技术【完整功能介绍+实现详情+源码】
|
4天前
|
XML Java 数据格式
Spring Cloud全解析:注册中心之zookeeper注册中心
使用ZooKeeper作为Spring Cloud的注册中心无需单独部署服务器,直接利用ZooKeeper服务端功能。项目通过`spring-cloud-starter-zookeeper-discovery`依赖实现服务注册与发现。配置文件指定连接地址,如`localhost:2181`。启动应用后,服务自动注册到ZooKeeper的`/services`路径下,形成临时节点,包含服务实例信息。
|
5天前
|
NoSQL 关系型数据库 MySQL
SpringBoot 集成 SpringSecurity + MySQL + JWT 附源码,废话不多直接盘
SpringBoot 集成 SpringSecurity + MySQL + JWT 附源码,废话不多直接盘
17 2
|
8天前
|
开发者 Python
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
34 1
|
8天前
|
开发者 Python
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
22 1
|
15天前
|
NoSQL Redis
redis 6源码解析之 ziplist
redis 6源码解析之 ziplist
16 5
|
4天前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
5天前
|
自然语言处理 Java 关系型数据库
ElasticSearch 实现分词全文检索 - SpringBoot 完整实现 Demo 附源码【完结篇】
ElasticSearch 实现分词全文检索 - SpringBoot 完整实现 Demo 附源码【完结篇】
12 0
|
15天前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
43 6

热门文章

最新文章

推荐镜像

更多