1. SpringBoot自动装载
Spring Boot 实现“自动装载”(Auto Configuration)是其最核心、最强大的功能之一,使得开发者可以快速搭建项目而无需进行复杂的 XML 配置。这一机制的底层实现主要依赖于 Spring Framework 的条件注解机制 和 Spring Boot 的 SPI 扩展机制。以下是从底层源码和原理出发的详细剖析。
一、核心目标
Spring Boot 自动装载(Auto Configuration)指的是,应用启动时自动根据类路径中存在的类、当前环境、配置等条件,自动创建和注册一些常用 Bean,而不需要显式配置。
二、核心机制概览
1. SpringFactoriesLoader + META-INF/spring.factories
这是自动配置的入口机制,Spring Boot 会扫描所有依赖中的 spring.factories
文件,并加载其中声明的自动配置类。
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
上述配置表示,Spring Boot 在启动时会自动加载这些类并尝试加入到 Spring 容器中。
2. @EnableAutoConfiguration
注解
位于 @SpringBootApplication
注解中。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
3. AutoConfigurationImportSelector
这是最核心的选择器,它会去读取 spring.factories
中定义的 EnableAutoConfiguration
条目,并决定哪些配置类应被加载。
核心逻辑(精简):
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 加载 spring.factories 中的自动配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 过滤不需要加载的类
configurations = removeDuplicates(configurations);
return configurations.toArray(new String[0]);
}
三、条件注解机制(决定是否真正加载某配置类)
自动配置类虽然被扫描到了,但不一定会生效。这依赖于一系列 @Conditional
注解判断当前环境是否满足。
常见的条件注解包括:
注解 | 含义 |
---|---|
@ConditionalOnClass |
类路径存在某个类时才生效 |
@ConditionalOnMissingBean |
仅当某个 Bean 未被定义时生效 |
@ConditionalOnProperty |
配置文件中存在某个属性时生效 |
@ConditionalOnBean |
容器中存在某个 Bean 时生效 |
例子(DataSourceAutoConfiguration
):
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
...
}
表示:仅当类路径中存在 javax.sql.DataSource
,并且容器中没有用户自己定义的 DataSource
时,才自动配置一个数据源。
四、自动装载的执行流程(源码视角)
@SpringBootApplication
|
@EnableAutoConfiguration
|
@Import(AutoConfigurationImportSelector.class)
|
AutoConfigurationImportSelector.selectImports()
|
SpringFactoriesLoader.loadFactoryNames()
|
读取 spring.factories 中的 EnableAutoConfiguration 配置项
|
加载对应的 Configuration 类
|
每个类会检查自身上的条件注解(如 @ConditionalOnClass)
|
符合条件的类才会最终注入容器
五、实战调试建议
你可以这样调试自动装载:
启用自动配置报告:
debug: true
启动后会在日志中输出:
正在加载的自动配置类
哪些配置类被排除了(并标明原因)
查看实际生效的 Bean:
$ mvn spring-boot:run $ curl /actuator/beans
禁用某些自动配置类:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
六、与 SPI (ServiceLoader) 的比较
Spring Boot 的 spring.factories
本质是 自定义 SPI 扩展机制 的一种增强形式:
标准 Java SPI 机制使用
META-INF/services/
;Spring Boot 用
META-INF/spring.factories
;加载方式通过
SpringFactoriesLoader
实现,更灵活、更强大(支持类名映射、值为多个类等)。
七、总结:关键组成列表
组件 | 功能 |
---|---|
@EnableAutoConfiguration |
启动自动配置功能 |
AutoConfigurationImportSelector |
加载配置类列表 |
spring.factories |
存储自动配置类清单 |
@Conditional 系列注解 |
控制配置类是否生效 |
SpringFactoriesLoader |
从 classpath 加载配置元数据 |
@Configuration + @Bean |
定义自动注入的 Bean |
2. 手写Spring Boot 自动装载模块
手写一个完整的 Spring Boot 自动装载模块(Starter),包括从零开始创建一个自定义 Starter、自动注册 Bean、条件装配,并说明每一步背后的原理。
一、自定义 Starter 的目标
我们要创建一个 my-logger-spring-boot-starter
:
提供一个日志打印工具类
MyLogger
。如果配置中开启了
my.logger.enabled=true
,自动将它注册为 Spring Bean。用户只需要添加依赖,不需要写任何配置或注解即可使用。
二、模块结构
my-logger-spring-boot-starter/
├── src/
│ └── main/
│ ├── java/
│ │ └── com/example/logger/
│ │ ├── MyLogger.java
│ │ ├── MyLoggerAutoConfiguration.java
│ │ └── condition/ConditionalOnMyLoggerEnabled.java
│ └── resources/
│ └── META-INF/
│ └── spring.factories
└── pom.xml
三、核心代码实现
1. MyLogger
:要自动注册的 Bean
package com.example.logger;
public class MyLogger {
public void log(String msg) {
System.out.println("[MyLogger] " + msg);
}
}
2. 条件注解:@ConditionalOnMyLoggerEnabled
package com.example.logger.condition;
import org.springframework.context.annotation.Conditional;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyLoggerEnabledCondition.class)
public @interface ConditionalOnMyLoggerEnabled {
}
实现对应的条件判断类:
package com.example.logger.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class MyLoggerEnabledCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 读取配置项 my.logger.enabled,默认 false
String enabled = context.getEnvironment().getProperty("my.logger.enabled", "false");
return Boolean.parseBoolean(enabled);
}
}
3. 自动配置类:MyLoggerAutoConfiguration
package com.example.logger;
import com.example.logger.condition.ConditionalOnMyLoggerEnabled;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnMyLoggerEnabled
public class MyLoggerAutoConfiguration {
@Bean
public MyLogger myLogger() {
return new MyLogger();
}
}
4. spring.factories
文件
# src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.logger.MyLoggerAutoConfiguration
被 Spring Boot 的
AutoConfigurationImportSelector
读取,加入到候选配置类中。
5. pom.xml
添加依赖打包标识
确保这是一个 Starter 模块:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
四、使用方式(在业务系统中)
业务系统只需:
添加依赖:
<dependency>
<groupId>com.example</groupId>
<artifactId>my-logger-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
配置启用项:
my:
logger:
enabled: true
注入并使用:
@RestController
public class TestController {
@Autowired
private MyLogger myLogger;
@GetMapping("/log")
public String log() {
myLogger.log("Hello from custom logger");
return "logged";
}
}
五、验证自动配置是否生效
启动时日志中可看到 Spring Boot 输出自动配置报告。
使用
/actuator/beans
也能验证MyLogger
是否被注册。修改配置
my.logger.enabled=false
,即可验证它是否会被条件排除。
六、总结:底层自动装载要点再强调一次
机制 | 实现方式 |
---|---|
自动配置入口 | spring.factories + EnableAutoConfiguration |
条件生效控制 | 自定义 @Conditional 注解 |
SPI 机制扩展 | SpringFactoriesLoader |
配置绑定 | @ConfigurationProperties (可选) |
Bean 注册 | 标准 @Configuration + @Bean |