← 返回首页

第2章: 自动配置原理

深入理解Spring Boot的核心机制

什么是自动配置?

自动配置(Auto-Configuration)是 Spring Boot 的核心特性,它能够根据项目中的依赖自动配置 Spring 应用,极大地简化了开发工作。

自动配置的优势

💡 举个例子:

当你添加 spring-boot-starter-data-jpa 依赖后,Spring Boot 会自动配置:

  • 数据源(DataSource)
  • EntityManagerFactory
  • 事务管理器(TransactionManager)
  • JPA 仓库(Repository)

@SpringBootApplication 注解剖析

@SpringBootApplication 是一个组合注解,包含了三个核心注解。

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration // 1. 配置类 @EnableAutoConfiguration // 2. 启用自动配置 @ComponentScan // 3. 组件扫描 public @interface SpringBootApplication { // ... }

1. @SpringBootConfiguration

标记当前类为配置类,等同于 @Configuration。

@SpringBootConfiguration public class Application { @Bean public MyService myService() { return new MyService(); } }

2. @EnableAutoConfiguration

启用自动配置机制,这是 Spring Boot 的核心。

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { // 排除特定的自动配置类 Class[] exclude() default {}; String[] excludeName() default {}; }

3. @ComponentScan

扫描当前包及子包下的组件(@Component、@Service、@Repository、@Controller)。

// 默认扫描主类所在包及子包 @SpringBootApplication public class Application { // 自动扫描 com.example 及其子包 } // 自定义扫描路径 @SpringBootApplication @ComponentScan(basePackages = {"com.example", "com.other"}) public class Application { // ... }

自动配置原理详解

Spring Boot 的自动配置通过以下步骤实现:

步骤1:加载自动配置类

Spring Boot 启动时,会读取 META-INF/spring.factories 文件,加载所有的自动配置类。

# spring-boot-autoconfigure.jar 中的 spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ ...

步骤2:条件化配置

每个自动配置类都使用 @Conditional 注解,只有满足条件才会生效。

@Configuration @ConditionalOnClass(DataSource.class) // 类路径存在 DataSource @ConditionalOnMissingBean(DataSource.class) // 容器中没有 DataSource Bean @EnableConfigurationProperties(DataSourceProperties.class) public class DataSourceAutoConfiguration { @Bean @ConditionalOnProperty(name = "spring.datasource.type") public DataSource dataSource(DataSourceProperties properties) { // 创建数据源 return DataSourceBuilder.create() .url(properties.getUrl()) .username(properties.getUsername()) .password(properties.getPassword()) .build(); } }

常用条件注解

注解 说明
@ConditionalOnClass 类路径存在指定类时生效
@ConditionalOnMissingClass 类路径不存在指定类时生效
@ConditionalOnBean 容器中存在指定 Bean 时生效
@ConditionalOnMissingBean 容器中不存在指定 Bean 时生效
@ConditionalOnProperty 配置文件中存在指定属性时生效
@ConditionalOnWebApplication Web 应用时生效

自定义自动配置

我们可以创建自己的自动配置类,实现类似 Spring Boot 的自动配置功能。

1. 创建配置属性类

@ConfigurationProperties(prefix = "myapp") public class MyAppProperties { private String name = "默认应用"; private String version = "1.0.0"; private boolean enabled = true; // getter/setter public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } }

2. 创建自动配置类

@Configuration @ConditionalOnClass(MyService.class) @EnableConfigurationProperties(MyAppProperties.class) public class MyAppAutoConfiguration { @Autowired private MyAppProperties properties; @Bean @ConditionalOnMissingBean public MyService myService() { MyService service = new MyService(); service.setName(properties.getName()); service.setVersion(properties.getVersion()); return service; } @Bean @ConditionalOnProperty(name = "myapp.enabled", havingValue = "true") public MyInitializer myInitializer() { return new MyInitializer(); } }

3. 创建 spring.factories

在 resources/META-INF/spring.factories 文件中注册自动配置类:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.autoconfigure.MyAppAutoConfiguration

4. 使用配置

# application.yml myapp: name: 我的应用 version: 2.0.0 enabled: true

配置文件绑定

Spring Boot 提供了多种方式将配置文件的值绑定到 Java 对象。

方式1:@ConfigurationProperties

@Component @ConfigurationProperties(prefix = "server") public class ServerConfig { private int port; private String host; private int timeout; // getter/setter } // application.yml server: port: 8080 host: localhost timeout: 30

方式2:@Value

@Component public class AppConfig { @Value("${app.name}") private String appName; @Value("${app.version:1.0.0}") // 默认值 private String version; @Value("${app.enabled:true}") private boolean enabled; }

方式3:Environment

@Component public class ConfigReader { @Autowired private Environment env; public void readConfig() { String appName = env.getProperty("app.name"); int port = env.getProperty("server.port", Integer.class, 8080); boolean enabled = env.getProperty("app.enabled", Boolean.class, true); } }
💡 最佳实践:
  • 使用 @ConfigurationProperties 管理复杂配置
  • 使用 @Value 注入简单配置
  • 使用 Environment 动态读取配置

多环境配置

Spring Boot 支持为不同环境(开发、测试、生产)提供不同的配置。

配置文件命名规则

application.yml # 默认配置 application-dev.yml # 开发环境 application-test.yml # 测试环境 application-prod.yml # 生产环境

application.yml(主配置)

spring: profiles: active: dev # 激活开发环境 # 公共配置 app: name: SpringBoot Demo

application-dev.yml(开发环境)

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/dev_db username: dev_user password: dev_pass logging: level: root: DEBUG

application-prod.yml(生产环境)

server: port: 80 spring: datasource: url: jdbc:mysql://prod-server:3306/prod_db username: prod_user password: ${DB_PASSWORD} # 从环境变量读取 logging: level: root: WARN

激活环境的方式

# 方式1:配置文件 spring.profiles.active=prod # 方式2:命令行参数 java -jar app.jar --spring.profiles.active=prod # 方式3:环境变量 export SPRING_PROFILES_ACTIVE=prod # 方式4:IDE 配置 -Dspring.profiles.active=prod

@Profile 注解

@Configuration public class DataSourceConfig { @Bean @Profile("dev") public DataSource devDataSource() { // 开发环境数据源 return new HikariDataSource(); } @Bean @Profile("prod") public DataSource prodDataSource() { // 生产环境数据源 return new DruidDataSource(); } }

排除自动配置

有时我们需要排除某些自动配置类。

方式1:@SpringBootApplication 注解

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, RedisAutoConfiguration.class }) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

方式2:配置文件

# application.yml spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

查看自动配置报告

# 启动时添加参数 java -jar app.jar --debug # 或在配置文件中 debug: true # 输出示例: ============================ CONDITIONS EVALUATION REPORT ============================ Positive matches: # 生效的配置 ----------------- DataSourceAutoConfiguration matched: - @ConditionalOnClass found required classes 'javax.sql.DataSource' Negative matches: # 未生效的配置 ----------------- RedisAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'redis.clients.jedis.Jedis'

实战演示

自动配置流程演示

点击按钮查看演示

本章小结

← 上一章 下一章 →