# SpringBoot3教程 - 19 自动配置原理

请确定你已经看了前面的组件注册,如果没有,看完再来看这个。

前面已经介绍了组件的注册,在组件注册的时候,介绍了 @Import 注解和 ImportSelector 接口的使用,在接口中通过读取 .imports 文件来将文件中配置的类,自动注入到 Spring IOC 容器中。

但是上面还是要我们手动来通过使用 @Import 注解来注入,那么第三方的组件是如何实现自动配置的呢?

例如进行 web 开发,引入了 spring-boot-starter-web 就能实现 web 功能的自动配置呢?

下面我们来梳理一下自动配置的原理。

# 19.1 自动配置原理

1、主启动类上有一个 @SpringBootApplication 注解, @SpringBootApplication 注解是个复合注解,包含了@EnableAutoConfiguration 注解,@EnableAutoConfiguration 会触发 Spring Boot 自动配置机制,扫描并加载所有符合条件的自动配置类。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    // ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

2、@EnableAutoConfiguration 注解也是一个复合注解,其中包含了 @Import 注解,通过 @Import 注解导入了 AutoConfigurationImportSelector 类。

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

3、AutoConfigurationImportSelector 类是 ImportSelector 接口的实现类,查看 AutoConfigurationImportSelector 类的 selectImports() 方法,经过层层调用,是将 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中配置的自动配置类加载到应用的上下文。

// DeferredImportSelector继承自ImportSelector接口
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    // ...

    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            // 层层调用
            AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }
  
    // ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中的配置,在 SpringBoot 2.7 之前是写在 META-INFO/spring.factories 文件,2.7 到 3.0 之前同时兼容.imports 文件和 .factories 文件,3.0 以后使用 .imports 文件。

SpringBoot 会扫描所有类路径下的 jar 包,并将 jar 包中的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中配置的自动类加载到应用上下文中,这些配置类通常带有 @AutoConfiguration 注解,和各种条件注解(如 @ConditionalOnClass, @ConditionalOnProperty, @ConditionalOnMissingBean 等)。这些条件会在加载自动配置类之前进行评估,以决定是否应该实际应用这些配置。如果满足条件,则配置类中的 @Bean 方法会被调用,其返回的 Bean 实例会被注册到 Spring IOC 容器中。这样,这些 Bean 就成为了 Spring 应用上下文的一部分,可以被其他组件注入和使用。


在下一章,我们将实现如何自定义starter。