文章目录
- Bean 依赖的属性配置管理
-
- 属性类定义
- 业务功能 Bean 定义
- 配置文件示例
- 自动配置原理详解
-
- 自动配置的工作流程
- 自动配置实战示例:短信服务
-
- 定义核心功能类
- 定义配置属性类
- 创建自动配置类
- 注册自动配置类
- 使用自动配置
- 工作流程总结
- 自定义自动配置行为
-
- 通过 YAML 配置排除
- 通过注解参数排除
- 通过排除坐标控制
Bean 依赖的属性配置管理
了解 Bean 依赖的属性配置管理是理解 SpringBoot 自动配置原理的前提。
属性类定义
将业务功能 Bean 运行所需的资源抽取为独立的属性类(xxxProperties)读取配置文件信息。以短信服务为例:
@Data
@ConfigurationProperties("sms")
public class SmsProperties {
/**
* 访问密钥
*/
private String accessKey = "default-access-key";
/**
* 密钥
*/
private String secretKey = "default-secret-key";
/**
* 短信签名
*/
private String signName = "默认签名";
}
注意:@ConfigurationProperties 类通常不需要 @Component 注解,而是通过 @EnableConfigurationProperties 来启用,这样可以更好地控制 Bean 的加载时机。
业务功能 Bean 定义
定义业务功能 Bean,通过 @EnableConfigurationProperties 启用属性类,并在构造函数中注入属性配置:
@Slf4j
@Component
@EnableConfigurationProperties(SmsProperties.class)
public class SimpleSmsClient {
private String accessKey;
private String secretKey;
private String signName;
public SimpleSmsClient(SmsProperties smsProperties) {
this.accessKey = smsProperties.getAccessKey();
this.secretKey = smsProperties.getSecretKey();
this.signName = smsProperties.getSignName();
log.info("短信客户端初始化完成,签名:{}", signName);
}
public void send(String phone, String content) {
log.info("发送短信 -> 手机号:{},内容:{},签名:{}", phone, content, signName);
// 实际发送短信的逻辑
}
}
配置文件示例
这样就简单的实现了 Bean 依赖的属性管理,解耦了 Bean 的强制加载,并通过设置默认值的方式解耦了属性的强制依赖。在 SpringBoot 配置文件 application.yml 中,可以定义属性 Bean 需要的属性来覆盖默认值:
sms:
access-key: your–access–key
secret-key: your–secret–key
sign-name: 我的应用
如果不配置这些属性,Bean 将使用 SmsProperties 中定义的默认值。这种方式实现了配置的灵活性,既可以使用默认配置快速启动,也可以根据实际需求自定义配置。
自动配置原理详解
自动配置是指 SpringBoot 根据开发者引入的依赖类,自动加载可能使用到的 Bean。其核心价值在于提升开发效率。自动配置可能需要配置相关参数,例如 MySQL 数据源的配置等。
自动配置的工作流程
自动配置的核心思想可以概括为:
初始化环境:SpringBoot 初始化 Spring 容器的基础环境,读取用户的配置信息,加载用户自定义的 Bean 和引入的其他依赖坐标,形成初始化环境;
加载技术集:SpringBoot 在启动时通过读取 classpath 下所有 jar 包中的配置文件来加载技术集 A 包含的所有自动配置类(此时加载的部分内容可能是无效或无作用的)。具体机制为:
- Spring Boot 2.7 之前:读取 META-INF/spring.factories 文件中 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键对应的自动配置类列表
- Spring Boot 2.7+:读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中声明的自动配置类列表
条件匹配:SpringBoot 为技术集 A 中的每一个技术约定了启动该技术所对应的条件,并设置为按条件加载。由于开发者引入了一些 Bean 和其他依赖坐标,即形成了初始化环境,此时根据该初始化环境与 SpringBoot 的技术集 A 进行匹配,将满足条件的技术进行加载;
默认配置:由于某些技术不进行配置就无法正常工作,因此 SpringBoot 引入了设置集 B。SpringBoot 统计了各个国家各个行业的开发者使用某个技术时最常用的配置,然后将这些配置作为默认值直接设置(SpringBoot 默认配置);
配置覆盖:在不需要默认配置的情况下,可以通过 SpringBoot 开放的修改设置集 B 的接口对默认配置进行覆盖。
自动配置实战示例:短信服务
以短信服务为例,演示如何开发一个自动配置功能,让用户只需引入依赖并配置参数,就能直接使用短信发送功能。
定义核心功能类
首先定义短信服务类,这是实际提供业务功能的类,该技术隶属于上述的技术集 A:
@Slf4j
public class SmsService {
private String accessKey;
private String secretKey;
private String signName;
public SmsService(String accessKey, String secretKey, String signName) {
this.accessKey = accessKey;
this.secretKey = secretKey;
this.signName = signName;
log.info("短信服务初始化完成,签名:{}", signName);
}
/**
* 发送短信
*/
public boolean sendSms(String phone, String content) {
log.info("发送短信 -> 手机号:{},内容:{},签名:{}", phone, content, signName);
// 实际发送短信的逻辑(这里简化处理)
return true;
}
}
定义配置属性类
定义一个属性类来封装短信服务的配置参数,该配置隶属于上述的设置集 B:
@Data
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
/**
* 访问密钥
*/
private String accessKey = "default-access-key";
/**
* 密钥
*/
private String secretKey = "default-secret-key";
/**
* 短信签名
*/
private String signName = "默认签名";
/**
* 是否启用短信服务
*/
private boolean enabled = true;
}
创建自动配置类
创建自动配置类,当满足条件时自动创建 SmsService Bean:
@Configuration
@EnableConfigurationProperties(SmsProperties.class)
@ConditionalOnProperty(prefix = "sms", name = "enabled", havingValue = "true", matchIfMissing = true)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean(SmsService.class)
public SmsService smsService(SmsProperties properties) {
return new SmsService(
properties.getAccessKey(),
properties.getSecretKey(),
properties.getSignName()
);
}
}
关键注解说明:
- @Configuration:标识这是一个配置类
- @EnableConfigurationProperties:启用配置属性类,将 SmsProperties 注入到容器
- @ConditionalOnProperty:条件装配,只有当 sms.enabled=true 时才加载(默认为 true)
- @ConditionalOnMissingBean(SmsService.class):当容器中不存在 SmsService 时才创建,允许用户自定义覆盖
注册自动配置类
在 resources 目录下创建自动配置文件,让 SpringBoot 能够发现这个自动配置类:
Spring Boot 2.7 之前的方式:创建 META-INF/spring.factories 文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
com.example.sms.autoconfigure.SmsAutoConfiguration
Spring Boot 2.7+ 推荐方式:创建 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件
com.example.sms.autoconfigure.SmsAutoConfiguration
使用自动配置
在 application.yml 中配置参数:
sms:
enabled: true
access-key: your–access–key
secret-key: your–secret–key
sign-name: 我的应用
在业务代码中直接注入使用:
@RestController
public class UserController {
@Autowired
private SmsService smsService;
@PostMapping("/sendCode")
public String sendVerificationCode(String phone) {
String code = "123456";
smsService.sendSms(phone, "您的验证码是:" + code);
return "发送成功";
}
}
工作流程总结
- Spring Boot 2.7 之前:扫描 META-INF/spring.factories 文件
- Spring Boot 2.7+:扫描 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件
这样,用户只需引入依赖、添加配置,就能自动获得短信发送功能,无需手动创建 Bean,体现了 SpringBoot “约定优于配置” 的设计理念。
自定义自动配置行为
SpringBoot 的自动配置并非强制执行,可以通过配置的形式干预是否启用对应的自动配置功能。
对于自动配置的执行过程,可以根据自动配置流程进行一些高级定制。例如系统默认会加载 100 多种自动配置的技术,可以手动干预此工程,禁用自动配置。
通过 YAML 配置排除
通过 YAML 配置设置排除指定的自动配置类:
spring:
autoconfigure:
exclude:
– org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
通过注解参数排除
通过注解参数排除自动配置类:
// 在启动类或配置类上使用,排除指定的自动配置类
@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 或者使用 excludeName 通过类名字符串排除
@EnableAutoConfiguration(excludeName = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration")
通过排除坐标控制
如果当前自动配置中包含有更多的自动配置功能,也就是一个套娃的效果。此时可以通过检测条件的控制来管理自动配置是否启动。
例如 web 程序启动时会自动启动 tomcat 服务器,可以通过排除坐标的方式,让加载 tomcat 服务器的条件失效。不过需要提醒一点,你把 tomcat 排除掉,记得再加一种可以运行的服务器。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!–web起步依赖环境中,排除Tomcat起步依赖,匹配自动配置条件–>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!–添加Jetty起步依赖,匹配自动配置条件–>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>


