Spring-boot自动装配

Spring Boot 的自动装配(Auto-Configuration)是其核心特性之一,它通过条件化配置和类路径扫描,快速实现应用的配置自动化装配。Spring 中 bean 有三种装配机制,分别是:

  • 在 xml 中显式配置;
  • 在 java 中显式配置;
  • 隐式的 bean 发现机制和自动装配。

Spring 的自动装配需要从两个角度来实现,或者说是两个操作:

  • 组件扫描(component scanning):spring 会自动发现应用上下文中所创建的 bean;
  • 自动装配(autowiring):spring 自动满足 bean 之间的依赖,也就是我们说的 IoC/DI;

自动装配原理

Spring Boot 在启动时会扫描所有 jar 包中的 META-INF/spring.factories/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件, 加载文件中配置的类:

1
com.ares.config.ratelimit.RateLimiterAutoConfiguration

在Spring Boot 2.4之前的版本中META-INFO/spring.factories文件:

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ares.config.ratelimit.RateLimiterAutoConfiguration

新版本中AutoConfiguration.imports替换spring.factories文件原因:

  • 提高可读性和维护性
  • 增强的性能
  • 增加条件化装配
  • 向生态系统演进

springboot自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector 类来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Class<?>[] exclude() default {};

String[] excludeName() default {};
}
  • @AutoConfigurationPackage:将main包下的所有组件注册到容器中
  • @Import(AutoConfigurationImportSelector.class):加载自动装配类 xxxAutoconfiguration

AutoConfigurationImportSelector

AutoConfigurationImportSelector 实现了 ImportSelector 接口,它会:

  • 读取 META-INF/spring.factories(新版本META-INF/spring.factories/org.springframework.boot.autoconfigure.AutoConfiguration.imports) 文件中的配置
  • 筛选出 EnableAutoConfiguration 对应的配置类
  • 过滤掉不符合条件的配置类
  • 将符合条件的配置类返回给 Spring 容器进行加载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class AutoConfigurationImportSelector implements 
DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

private ConfigurableListableBeanFactory beanFactory;
private Environment environment;
private ClassLoader beanClassLoader;
private ResourceLoader resourceLoader;
private ConfigurationClassFilter configurationClassFilter;

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}

AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}

AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
// 1.
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 2.
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 3.
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
// 4.
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}

代码逻辑说明:

  1. 判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置。
  2. 用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
  3. 获取需要自动装配的所有配置类,读取META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。这一步不光是这个依赖下的META-INF/spring.factories被读取到,所有 Spring Boot Starter 下的META-INF/spring.factories都会被读取到。
  4. 这一步经历了getConfigurationClassFilter().filter(configurations)一遍筛选,@ConditionalOnXXX 中的所有条件都满足,该类才会生效。所以并不是把spring.factories中的配置都加载。

ConditionalOnxxx

自动配置类通常使用条件注解来决定是否生效,常见的条件注解包括:

  • @ConditionalOnClass:当类路径下有指定的类时
  • @ConditionalOnMissingClass:当类路径下没有指定的类时
  • @ConditionalOnBean:当容器中有指定的Bean时
  • @ConditionalOnMissingBean:当容器中没有指定的Bean时
  • @ConditionalOnProperty:当配置文件中有指定的属性时
  • @ConditionalOnWebApplication:当应用是Web应用时

小结

自动装配的执行流程:

  1. Spring Boot 启动时,@SpringBootApplication 注解被解析
  2. @EnableAutoConfiguration 注解导入 AutoConfigurationImportSelector
  3. AutoConfigurationImportSelector 读取 classpath 下所有 jar 包中的 META-INF/spring.factories 文件
  4. 找出所有标注了 EnableAutoConfiguration 的配置类
  5. 通过条件注解对配置类进行过滤
  6. 将符合条件的配置类加载到 Spring 容器中
  7. 配置类中定义的 Bean 被创建并注册到容器中

示例

  • 添加依赖
1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
  • 定义配置属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Setter
@Getter
@NoArgsConstructor
@ConfigurationProperties(prefix = "snd.webclient")
public class CustomWebClientProperties {
/**
* 服务地址,不填写则为 http://serviceName
*/
private String url;
/**
* 微服务名称,不填写就是 configs 这个 map 的 key
*/
private String serverName;
/**
* 连接超时时间
*/
private int connectTimeout = 300;

/**
* 响应超时时间
*/
private int readTimeout = 3000;

/**
* 是否启用日志
*/
private boolean enableLogging = false;

}
  • 定义Factory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class CustomWebClientFactory {
private final WebClient.Builder webClientBuilder;

public CustomWebClientFactory(WebClient.Builder webClientBuilder) {
this.webClientBuilder = webClientBuilder;
}

public WebClient createWebClient() {
return webClientBuilder.build();
}

public WebClient createWebClient(String baseUrl) {
return webClientBuilder.baseUrl(baseUrl).build();
}

public WebClient createWebClient(String baseUrl, String serverName) {
return webClientBuilder.baseUrl(baseUrl).defaultHeader("server-name", serverName).build();
}
}
  • 定义WebClientFactoryAutoConfiguration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Configuration
@ConditionalOnClass(WebClient.class)
@EnableConfigurationProperties(CustomWebClientProperties.class)
@AutoConfigureAfter(WebClient.class)
public class WebClientFactoryAutoConfiguration {

private final Logger logger = LoggerFactory.getLogger(WebClientFactoryAutoConfiguration.class);

@Bean
@LoadBalanced // Add this annotation for service discovery
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}

/**
* WebClient的配置类
*
* @param webClientBuilder WebClient.Builder
* @param properties 配置属性
* @return CustomWebClientFactory
*/
@Bean
@LoadBalanced
@ConditionalOnMissingBean
CustomWebClientFactory customWebClientFactory(WebClient.Builder webClientBuilder,
CustomWebClientProperties properties) {

// 使用属性配置
if (properties.getUrl() != null) {
webClientBuilder.baseUrl(properties.getUrl());
} else if (properties.getServerName() != null) {
webClientBuilder.baseUrl(String.format("lb://%s", properties.getServerName()));
}

// 设置超时
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, properties.getConnectTimeout())
.responseTimeout(Duration.ofMillis(properties.getReadTimeout()));

webClientBuilder.clientConnector(new ReactorClientHttpConnector(httpClient));

// 设置日志
if (properties.isEnableLogging()) {
webClientBuilder.filter((request, next) -> {
logger.info("Request: {} {}", request.method(), request.url());
return next.exchange(request);
});
}

return new CustomWebClientFactory(webClientBuilder);
}
}
  • META-INF/spring
    在文件org.springframework.boot.autoconfigure.AutoConfiguration.imports中添加:
1
com.ares.config.webclient.WebClientFactoryAutoConfiguration

Spring-boot自动装配
http://example.com/2025/06/11/spring-boot自动装配原理/
作者
ares
发布于
2025年6月11日
许可协议