-
精尽Spring Boot源码分析 - 剖析 @SpringBootApplication 注解
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读
Spring Boot 版本:2.2.x
最好对 Spring 源码有一定的了解,可以先查看我的 《死磕 Spring 之 IoC 篇 - 文章导读》 系列文章
如果该篇内容对您有帮助,麻烦点击一下“推荐”,也可以关注博主,感激不尽~
该系列其他文章请查看:《精尽 Spring Boot 源码分析 - 文章导读》
概述
现如今,Spring Boot
在许多中大型企业中被普及,想必大家对于 @SpringBootApplication
并不陌生,这个注解通常标注在我们应用的启动类上面,标记是一个 Spring Boot 应用,同时开启自动配置的功能,那么你是否有深入了解过该注解呢?没有的话,或许这篇文章可以让你对它有一个新的认识。
提示:
@EnableAutoConfiguration
是开启自动配置功能的模块驱动注解,是 Spring Boot 的核心注解整篇文章主要是对这个注解,也就是 Spring Boot 的自动配置功能进行展述
@SpringBootApplication
org.springframework.boot.autoconfigure.SpringBootApplication
注解在 Spring Boot 的 spring-boot-autoconfigre
子模块下,当我们引入 spring-boot-starter
模块后会自动引入该子模块
该注解是一个组合注解,如下:
@SpringBootApplication
注解就是一个组合注解,里面的每个配置都是元注解中对应的属性,上面已做描述
该注解上面的 @Inherited
元注解是 Java 提供的,标注后表示当前注解定义在某个类上时,其子类会继承该注解,我们一起来看看其他三个注解
@SpringBootConfiguration
org.springframework.boot.SpringBootConfiguration
注解,Spring Boot 自定义注解
该注解很简单,上面标注了 @Configuration
元注解,所以作用相同,同样是将一个类标注为配置类,能够作为一个 Bean 被 Spring IoC 容器管理
至于为什么不直接使用 @Configuration
注解呢,我想这应该是 领域驱动设计 中的一种思想,可以使得 Spring Boot 更加灵活,总有它的用武之地
领域驱动设计:Domain-Driven Design,简称 DDD。过去系统分析和系统设计都是分离的,这样割裂的结果导致需求分析的结果无法直接进行设计编程,而能够进行编程运行的代码却扭曲需求,导致客户运行软件后才发现很多功能不是自己想要的,而且软件不能快速跟随需求变化。DDD 则打破了这种隔阂,提出了领域模型概念,统一了分析和设计编程,使得软件能够更灵活快速跟随需求变化。
@ComponentScan
org.springframework.context.annotation.ComponentScan
注解,Spring 注解,扫描指定路径下的标有 @Component
注解的类,解析成 Bean 被 Spring IoC 容器管理
想深入了解该注解的小伙伴可以查看我前面对 Spring IoC 进行源码分析的文章:
- 《死磕Spring之IoC篇 - @Bean 等注解的实现原理》
- 《死磕Spring之IoC篇 - BeanDefinition 的解析过程(面向注解)》
该注解通常需要和 @Configuration
注解一起使用,因为需要先被当做一个配置类,然后解析到上面有 @ComponentScan
注解后则处理该注解,通过 ClassPathBeanDefinitionScanner 扫描器去扫描指定路径下标注了 @Component
注解的类,将他们解析成 BeanDefinition(Bean 的前身),后续则会生成对应的 Bean 被 Spring IoC 容器管理
当然,如果该注解没有通过 basePackages
指定路径,Spring 会选在以该注解标注的类所在的包作为基础路径,然后扫描包下面的这些类
@EnableAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration
注解,Spring Boot 自定义注解,用于驱动 Spring Boot 自动配置模块
对于 Spring 中的模块驱动注解的实现都是通过 @Import
注解来实现的
模块驱动注解通常需要结合 @Configuration
注解一起使用,因为需要先被当做一个配置类,然后解析到上面有 @Import
注解后则进行处理,对于 @Import
注解的值有三种情况:
-
该 Class 对象实现了
ImportSelector
接口,调用它的selectImports(..)
方法获取需要被处理的 Class 对象的名称,也就是可以将它们作为一个 Bean 被 Spring IoC 管理-
该 Class 对象实现了
DeferredImportSelector
接口,和上者的执行时机不同,在所有配置类处理完后再执行,且支持@Order
排序
-
该 Class 对象实现了
-
该 Class 对象实现了
ImportBeanDefinitionRegistrar
接口,会调用它的registerBeanDefinitions(..)
方法,自定义地往 BeanDefinitionRegistry 注册中心注册 BeanDefinition(Bean 的前身) -
该 Class 对象是一个
@Configuration
配置类,会将这个类作为一个 Bean 被 Spring IoC 管理
对于 @Import
注解不熟悉的小伙伴可查看我前面的 《死磕Spring之IoC篇 - @Bean 等注解的实现原理》 这篇文章
这里的 @EnableAutoConfiguration
自动配置模块驱动注解,通过 @Import
导入 AutoConfigurationImportSelector 这个类(实现了 DeferredImportSelector
接口)来驱动 Spring Boot 的自动配置模块,下面会进行分析
@AutoConfigurationPackage
我们注意到 @EnableAutoConfiguration
注解上面还有一个 @AutoConfigurationPackage
元注解,它的作用就是注册一个 Bean,保存了当前注解标注的类所在包路径
同样这里使用了 @Import
注解来实现的,对应的是一个 AutoConfigurationPackages.Registrar
内部类,如下:
比较简单,这里直接跳过了
自动配置
在开始之前,我们先来了解一下 Spring Boot 的自动配置,就是通过引入某个功能的相关 jar
包依赖后,Spring Boot 能够自动配置应用程序,让我们很方便的使用该功能
-
例如当你引入
spring-boot-starter-aop
后,会自动引入 AOP 相关的jar
包依赖,那么在spring-boot-autoconfigure
中有一个AopAutoConfiguration
自动配置类会自动驱动整个 AOP 模块 -
例如当你引入
spring-boot-starter-web
后,会自动引入 Spring MVC、Tomcat 相关的jar
包依赖,那么在spring-boot-autoconfigure
中会有相应的自动配置类会自动配置 Spring MVC
当然,还有许多自动配置类,结合这 Spring Boot 的 Starter 模块,让许多功能或者第三方 jar
包能够很简便的和 Spring Boot 整合在一起使用
现在很多开源框架都提供了对应的 Spring Boot Starter 模块,能够更好的整合 Spring Boot,当你熟悉自动配置功能后,你也可以很轻松的写一个 Starter 包供他人使用