# Spring Boot 核心原理 ## 问题 1. Spring Boot 的自动配置原理是什么? 2. @SpringBootApplication 注解包含哪些核心注解? 3. Spring Boot 的启动流程是怎样的? 4. 什么是条件注解(@Conditional)? 5. Spring Boot 如何实现配置文件加载? 6. Spring Boot 的健康检查和监控如何实现? 7. Spring Boot 的 Starter 原理是什么? --- ## 标准答案 ### 1. @SpringBootApplication 注解 ```java @SpringBootConfiguration // 1. 配置类 @EnableAutoConfiguration // 2. 自动配置 @ComponentScan // 3. 组件扫描 public @interface SpringBootApplication { } ``` --- #### **1. @SpringBootConfiguration** ```java @Configuration // 本质上是 @Configuration public @interface SpringBootConfiguration { } ``` **作用**:标记为配置类(等同于 XML 配置文件) --- #### **2. @EnableAutoConfiguration** ```java @AutoConfigurationPackage // 自动配置包 @Import(AutoConfigurationImportSelector.class) // 导入自动配置类 public @interface EnableAutoConfiguration { } ``` **核心**:`AutoConfigurationImportSelector` ```java // 加载 META-INF/spring.factories 中的自动配置类 String[] configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader() ); ``` --- #### **3. @ComponentScan** ```java @ComponentScan( excludeFilters = { // 排除过滤器 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) } ) ``` **作用**:扫描 `@Component`、`@Service`、`@Repository`、`@Controller` 等注解 --- ### 2. 自动配置原理 #### **核心流程** ``` 1. @EnableAutoConfiguration ↓ 2. 加载 META-INF/spring.factories ↓ 3. 根据 @Conditional 条件注解决定是否加载配置 ↓ 4. 注册 Bean ``` --- #### **spring.factories 示例** ```properties # spring-boot-autoconfigure-2.7.0.jar org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ ... ``` --- #### **条件注解示例** ```java @Configuration @ConditionalOnClass(DataSource.class) // 类路径存在 DataSource @ConditionalOnMissingBean(DataSource.class) // 容器中不存在 DataSource Bean @EnableConfigurationProperties(DataSourceProperties.class) public class DataSourceAutoConfiguration { @Bean public DataSource dataSource(DataSourceProperties properties) { // 创建 DataSource return properties.initializeDataSourceBuilder().build(); } } ``` --- ### 3. Spring Boot 启动流程 ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` --- #### **核心步骤** ``` 1. 创建 SpringApplication ↓ 2. 准备 Environment ↓ 3. 打印 Banner ↓ 4. 创建 ApplicationContext ↓ 5. 刷新 Context(加载 Bean) ↓ 6. 调用 Runner(ApplicationRunner、CommandLineRunner) ``` --- #### **源码分析** ```java public SpringApplication(Class... primarySources) { // 1. 保存主配置类 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 2. 推断 Web 应用类型(SERVLET、REACTIVE、NONE) this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 3. 加载 ApplicationContextInitializer setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 4. 加载 ApplicationListener setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 5. 推断主类(main 方法所在类) this.mainApplicationClass = deduceMainApplicationClass(); } ``` --- ### 4. 配置文件加载 #### **加载顺序** ``` 1. 命令行参数(--server.port=8081) 2. Java 系统属性(System.getProperties()) 3. 操作系统环境变量 4. JAR 外部的 application-{profile}.properties 5. JAR 内部的 application-{profile}.properties 6. JAR 外部的 application.properties 7. JAR 内部的 application.properties 8. @PropertySource 9. 默认属性(SpringApplication.setDefaultProperties) ``` --- #### **配置文件示例** ```yaml # application.yml server: port: 8080 spring: profiles: active: dev --- spring: config: activate: on-profile: dev datasource: url: jdbc:mysql://localhost:3306/dev --- spring: config: activate: on-profile: prod datasource: url: jdbc:mysql://prod-db:3306/prod ``` --- ### 5. 自定义 Starter #### **步骤** **1. 创建 autoconfigure 模块**: ```java @Configuration @ConditionalOnClass(HelloService.class) @EnableConfigurationProperties(HelloProperties.class) public class HelloAutoConfiguration { @Bean @ConditionalOnMissingBean public HelloService helloService(HelloProperties properties) { return new HelloService(properties.getMessage()); } } ``` **2. 创建配置类**: ```java @ConfigurationProperties(prefix = "hello") public class HelloProperties { private String message = "Hello World"; // getter/setter } ``` **3. 创建 spring.factories**: ```properties # META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.hello.HelloAutoConfiguration ``` **4. 使用**: ```yaml # application.yml hello: message: Hello Spring Boot ``` ```java @Autowired private HelloService helloService; helloService.sayHello(); // 输出:Hello Spring Boot ``` --- ### 6. Actuator 监控 #### **依赖** ```xml org.springframework.boot spring-boot-starter-actuator ``` --- #### **配置** ```yaml management: endpoints: web: exposure: include: health,info,metrics,prometheus # 暴露端点 endpoint: health: show-details: always # 显示详细信息 ``` --- #### **常用端点** | 端点 | 说明 | 示例 | |------|------|------| | **/actuator/health** | 健康检查 | `{"status":"UP"}` | | **/actuator/info** | 应用信息 | 版本、描述等 | | **/actuator/metrics** | 指标 | JVM、HTTP 请求等 | | **/actuator/prometheus** | Prometheus 格式 | 监控数据 | | **/actuator/env** | 环境变量 | 配置属性 | | **/actuator/loggers** | 日志配置 | 日志级别 | --- #### **自定义健康检查** ```java @Component public class DatabaseHealthIndicator implements HealthIndicator { @Autowired private DataSource dataSource; @Override public Health health() { try (Connection conn = dataSource.getConnection()) { if (conn.isValid(1)) { return Health.up() .withDetail("database", "MySQL") .build(); } } catch (SQLException e) { return Health.down() .withException(e) .build(); } } } ``` --- ### 7. 阿里 P7 加分项 **深度理解**: - 理解 Spring Boot 的条件装配机制 - 理解 SpringApplication 的启动流程 - 理解 AutoConfigurationImportSelector 的工作原理 **实战经验**: - 有自定义 Starter 的经验 - 有解决自动配置冲突的经验 - 有 Spring Boot 性能优化的经验 **架构能力**: - 能设计可复用的 Spring Boot Starter - 能设计多环境配置方案 - 能设计微服务监控体系 **技术选型**: - 了解 Spring Boot 2.x vs 3.x 的区别 - 了解 GraalVM Native Image 的支持 - 了解 Quarkus、Micronaut 等替代框架