Spring Boot 是一个基于 Spring 框架的快速应用开发框架,它极大地简化了开发流程,使得开发者能够更加快速地构建应用程序。Spring Boot 中的一个关键特性就是自动配置(Auto-Configuration),这使得开发者无需手动编写大量的配置代码就能得到一个功能完善的 Spring 应用程序。
1.基本原理
Spring Boot 的自动配置是基于 Spring 框架的核心功能——依赖注入(Dependency Injection)和自动装配(Bean Auto-Wiring)。
1.1.启动类和 @SpringBootApplication
注解
启动类:Spring Boot 应用通常有一个主类,这个主类上会有一个 @SpringBootApplication
注解。
@SpringBootApplication
注解:该注解是一个组合注解
@SpringBootConfiguration
:表示这是一个 Spring 配置类。@EnableAutoConfiguration
:启用自动配置功能,告诉 Spring Boot 启动自动配置。@ComponentScan
:扫描指定包下的组件,以便于发现并装配带有@Component
、@Service
、@Repository
或@Controller
等注解的类。
1.2.@EnableAutoConfiguration
注解
@EnableAutoConfiguration
注解:该注解本身也是一个组合注解
@AutoConfigurationPackage
:这个注解会告诉 Spring Boot 扫描当前包以及子包中的@Component
相关的注解。@Import({AutoConfigurationImportSelector.class})
AutoConfigurationImportSelector
类:通过这个类,Spring Boot 会在启动时选择并导入一组自动配置类。
1.3.自动配置类的发现
-
AutoConfigurationImportSelector
类:在 Spring 容器启动过程中,这个类会从META-INF/spring.factories
文件中读取所有候选的自动配置类。 -
spring.factories
文件:位于每个自动配置模块的META-INF
目录下,包含了一系列的自动配置类和它们对应的条件,每个类都是一个配置项。 -
org.springframework.boot.autoconfigure.AutoConfiguration.imports
在
src/main/resources/META-INF/spring
文件夹下的org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件功能与spring.factories
一样。都是用来加载自动装配的类。两者目的都是为引入外部的jar,把外部bean纳入到Spring容器,实现外部组件与Spring的集成, 主要区别当前方式通过配置的信息创建内部是具体的要导入到Spring环境的中的配置类, 而
spring.factories
这种方式,内部是key-value的形式。注意:从spring boot2.7开始,慢慢不支持
META-INF/spring.factories
文件了需要导入的自动配置类可以放在
/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件中。
1.4.条件匹配
-
@Conditional
注解:自动配置类中的每个 Bean 都可能带有@Conditional
注解,它用来指定配置类生效的条件。 -
条件注解:例如
@ConditionalOnClass
、@ConditionalOnMissingClass
、@ConditionalOnBean
、@ConditionalOnMissingBean
等,这些注解可以帮助决定哪些自动配置类会被激活。@ConditionalOnClass
: 当指定的类位于类路径上时,才会启用被注解的组件或配置。这可用于根据类的可用性来决定是否启用某个特定功能。
@ConditionalOnMissingClass
: 当指定的类不在类路径上时,才会启用被注解的组件或配置。这可用于在某些类不可用时应用备用实现。
@ConditionalOnBean
: 当指定的 Bean 在应用程序上下文中存在时,才会启用被注解的组件或配置。这可以用于基于其他 Bean 的存在与否来决定是否启用特定功能。
@ConditionalOnMissingBean
: 当指定的 Bean 在应用程序上下文中不存在时,才会启用被注解的组件或配置。这可用于提供默认实现或避免重复创建 Bean。
@ConditionalOnProperty
: 当指定的属性满足条件时,才会启用被注解的组件或配置。这可用于基于配置属性的值来决定是否启用特定功能。
@ConditionalOnExpression
: 当指定的 SpEL 表达式计算结果为true
时,才会启用被注解的组件或配置。这可用于更复杂的条件判断。
1.5.自动配置类
- 自动配置类:每个自动配置类通常会针对一个特定的框架或技术栈(如 Tomcat、JPA、Redis 等)。
- 配置Bean:自动配置类内部会通过
@Bean
方法来注册 Bean 到 Spring 容器中。 - 属性绑定:自动配置类还可以通过
@ConfigurationProperties
注解来绑定配置文件中的属性到特定的 Java 对象上。
1.6.配置文件
application.properties
或application.yml
:这些文件包含了 Spring Boot 应用程序的配置信息,用于调整自动配置的行为。
1.7.Starter 依赖
Spring Boot 提供了一组“starter”依赖,这些依赖简化了项目的依赖管理。每个 starter 包含了构建典型应用所需的依赖项,而无需编写复杂的 XML 配置文件。例如,spring-boot-starter-web
包含了 Web 应用所需的所有依赖,如 Spring MVC、Tomcat(默认的嵌入式容器)等。
2.自动装配的过程
2.1 启动 Spring 应用
当你运行带有 @SpringBootApplication
注解的主类时,Spring Boot 会开始初始化 Spring 应用上下文。
2.2 导入自动配置
@EnableAutoConfiguration
:该注解触发了AutoConfigurationImportSelector
的执行。AutoConfigurationImportSelector
:这个类会根据类路径上的可用资源来决定应该导入哪些自动配置类。- 选择自动配置类:通过
getCandidateConfigurations()
方法,AutoConfigurationImportSelector
会读取spring.factories
文件中的配置,从中挑选出所有以org.springframework.boot.autoconfigure.
开头的配置类。
2.3 加载自动配置类
- 加载配置类:Spring 会将这些自动配置类加载到应用上下文中。
- 解析条件注解:对于每个自动配置类,Spring 会检查
@Conditional
注解来确定是否应该激活该配置类。 - 条件匹配:如果条件匹配成功,则会创建配置类的实例,并执行其
@Bean
方法来注册 Bean。
2.4 注册 Bean
- 注册 Bean:自动配置类中的
@Bean
方法会被执行,这些方法会创建并注册新的 Bean 到 Spring 容器中。 - 属性绑定:如果有
@ConfigurationProperties
注解,则会尝试从配置文件中读取相应的属性值并绑定到相应的 Java 对象上。
2.5 应用配置
- 最终配置:所有的自动配置完成后,Spring Boot 会将所有注册的 Bean 进行依赖注入,从而完成整个应用的初始化过程。
3.示例 :MyBatis
当使用 MyBatis 作为持久层框架时,Spring Boot 会自动配置 MyBatis 相关的组件,以简化 MyBatis 的集成。
3.1. 添加依赖
在 pom.xml
文件中添加 MyBatis 和 Spring Boot Starter MyBatis 的Starter 依赖:
mybatis-spring-boot-starter
,它会自动添加 MyBatis 和其他相关依赖,而不需要你显式声明每一个依赖。
<!-- Maven -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
3.2. 启动类
在启动类上 @SpringBootApplication
注解包含 @EnableAutoConfiguration
启动自动装配
3.3. 自动配置的发现
-
@EnableAutoConfiguration
:这个注解告诉 Spring Boot 启动自动配置过程。 -
AutoConfigurationImportSelector
:这个类负责从spring.factories
文件中读取所有候选的自动配置类。该文件列出了所有候选的自动配置类。# META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ ..., org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
-
spring.factories
文件:位于META-INF
目录下,包含了 MyBatis 相关的自动配置类,如org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
。
3.4. 自动配置类
-
MybatisAutoConfiguration
:这个类是 Spring Boot 为 MyBatis 提供的自动配置类,它负责配置 MyBatis 的核心组件。 -
条件注解:该类中的
@Bean
方法通常带有@Conditional
注解,用来控制自动配置的条件。类上的@ConditionalOnClass
来确认 MyBatis 类的存在,或者使用@ConditionalOnMissingBean
来避免重复配置。@Configuration @ConditionalOnClass({ SqlSessionFactory.class }) @EnableConfigurationProperties(MybatisProperties.class) @AutoConfigureBefore({ DataSourceAutoConfiguration.class, TransactionManagementAutoConfiguration.class }) public class MybatisAutoConfiguration { // ... }
3.5.属性绑定
类上的@EnableConfigurationProperties(MybatisProperties.class)
注解用来读取配置信息
@ConfigurationProperties(
prefix = "mybatis"
)
public class MybatisProperties {
...
}
通过 @ConfigurationProperties
从自 application.properties
或 application.yml
的配置文件中读取 mybatis.mapper-locations
配置信息
3.6.自动配置顺序@AutoConfigureAfter
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
MybatisAutoConfiguration
它依赖于 DataSourceAutoConfiguration
和 MybatisLanguageDriverAutoConfiguration
两个功能, 通过这个注解确保 MybatisAutoConfiguration
在这两个自动配置类之后被加载,以确保 MyBatis 可以正确地使用数据源和语言驱动配置。
其中 DataSourceAutoConfiguration
@AutoConfiguration(
before = {SqlInitializationAutoConfiguration.class}
)
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(
type = {"io.r2dbc.spi.ConnectionFactory"}
)
@EnableConfigurationProperties({DataSourceProperties.class})
@Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceCheckpointRestoreConfiguration.class})
public class DataSourceAutoConfiguration {
...
}
通过 DataSourceProperties
@ConfigurationProperties(
prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
...
private String driverClassName;
private String url;
private String username;
private String password;
...
}
读取 spring.datasource.url
、spring.datasource.username
和 spring.datasource.password
,绑定到 MybatisProperties
对象上 Spring Boot 就会自动创建一个数据库连接池。
3.7.注册 Bean
自动配置类通过 @Bean
方法来注册各种 Bean。例如,MybatisAutoConfiguration
会注册 SqlSessionFactory
、SqlSessionTemplate
和 MapperScannerConfigurer
等 Bean。
-
DataSource
:如果未显式配置DataSource
,Spring Boot 会自动创建一个DataSource
实例。 -
SqlSessionFactory
:MybatisAutoConfiguration
会创建SqlSessionFactory
,这是 MyBatis 的核心组件。 -
MapperScannerConfigurer
:用于扫描带有@Mapper
注解的接口,自动生成对应的 Mapper Bean。 -
TransactionManager
:如果使用了 JTA 或 DataSource 事务管理器,MybatisAutoConfiguration
也会配置事务管理器。
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
private final MybatisProperties properties;
private final DataSource dataSource;
public MybatisAutoConfiguration(DataSource dataSource, MybatisProperties properties) {
this.dataSource = dataSource;
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
// 更多配置...
return factory.getObject();
}
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass({ MapperFactoryBean.class, MapperScannerConfigurer.class })
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage(this.properties.getMapperLocations());
// 更多配置...
return mapperScannerConfigurer;
}
}
3.8.应用配置
最终配置:所有的自动配置完成后,Spring Boot 会将所有注册的 Bean 进行依赖注入,从而完成整个应用的初始化过程。
4.总结
Spring Boot 的自动配置过程主要包括以下几个步骤:
- 通过
@SpringBootApplication
注解启动自动配置。 - 通过
AutoConfigurationImportSelector
选择并导入自动配置类。 - 根据条件注解来确定哪些配置类应该被激活。
- 通过
@Bean
方法注册 Bean 到 Spring 容器中。 - 通过
@ConfigurationProperties
绑定配置文件中的属性到 Java 对象上。
通过这种方式,Spring Boot 大大简化了设置和配置 Spring 应用的过程,让开发者能够专注于业务逻辑而不是基础设施配置。