# 2.SpringBoot-自动配置原理

# 1.自动包规则原理

springboot应用启动类:

@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

}
1
2
3
4
5
6
7
8

@SpringBootApplication下的三个主要注解:

  • @SpringBootConfiguration

  • @EnableAutoConfiguration

  • @ComponentScan("com.demo.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

1)@SpringBootConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}
1
2
3
4
5
6
7
8
9
10
11

@Configuration代表他是一个配置类

2)@ComponentScan

指定扫描哪些包下的Spring注解。

3)@EnableAutoConfiguration

@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 {};
}
1
2
3
4
5
6
7
8
9
10
11
12
13

@AutoConfigurationPackage标签名直译为:自动配置包,指定了默认的包规则。

AutoConfigurationPackages类下register方法

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }

public static void register(BeanDefinitionRegistry registry, String... packageNames) {
        if (registry.containsBeanDefinition(BEAN)) {
            BasePackagesBeanDefinition beanDefinition = (BasePackagesBeanDefinition)registry.getBeanDefinition(BEAN);
            beanDefinition.addBasePackages(packageNames);
        } else {
            registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12

利用Register容器记录包路径导入包到容器中

让自动配置类能够感知到用户主启动类的位置,从而更好地完成自动配置工作。)


# 2.初始加载自动配置类

@Import({AutoConfigurationImportSelector.class})

1.利用getAutoConfigurationEntry(annotationMetadata)给容器批量导入一些组件

2.调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类

3.利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件

4.从META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件 spring-boot-autoconfigure-2.7.2.RELEASE.jar包里面也有META-INF/spring.factories

# 文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
# spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
...
1
2
3
4
5
6
7

虽然我们127个场景的所有自动配置启动的时候默认全部加载,但是xxxxAutoConfiguration按照条件装配规则(@Conditional),最终会按需配置。


# 3.自动配置流程

  • SpringBoot会先加载所有的自动配置类

  • 每个配置类都按照条件进行生效,默认都会绑定配置文件指定的值。(xxxProperties里面读取,xxxProperties和配置文件进行了绑定)

  • 生效的配置类就会给容器中装配很多组件,只要有这些组件,相当于功能就有了

  • 定制化配置

    • 用户自己去定义Bean替换底层组件(SpringBoot底层配置好了所有的组件,如果你自己配置了优先以用户定义的优先)
@Bean
    public CharacterEncodingFilter characterEncodingFilter(){
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return characterEncodingFilter;
    }
1
2
3
4
5
6
7
  • 从application.properties配置文件里面去修改默认属性值(xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 (绑定)----> application.properties)
server:
  port: 8888
  servlet:
    encoding:
      charset: UTF-8
1
2
3
4
5

注意:规范

@Bean
@ConditionalOnBean(MultipartResolver.class)  //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {//有参数的情况
    //给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
    //SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
    // Detect if the user has created a MultipartResolver but named it incorrectly
    return resolver;//给容器中加入了文件上传解析器;
}
1
2
3
4
5
6
7
8
9

也就是说为了规范,他会将你注册命名的组件以规范的方式重新给你命名。


# 4.自动配置-总结

1)找到@SpringBootApplication 注解中的@EnableAutoConfiguration

2)@EnableAutoConfiguration注解中的@AutoConfigurationPackages会利用Register容器记录启动类所在的包路径,导入包路径到spring容器中

3)加载自动配置类:AutoConfigurationImportSelector读取 Spring Boot中spring-boot-autoconfigure包的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件加载到容器中

4)@Conditional 系列注解判断自动配置类是否生效,若生效,默认绑定配置文件指定的值

5)注册 Bean 到容器

组件 / 文件 作用
@EnableAutoConfiguration 开启自动配置的核心注解
@AutoConfigurationPackages 导入包路径到spring容器中
AutoConfigurationImportSelector 加载自动配置类清单的核心类
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 自动配置类的清单文件(Spring Boot 2.7+ 替代旧的 spring.factories)
@Conditional 系列注解 条件筛选,控制自动配置类是否生效
spring-boot-autoconfigure 依赖 包含所有内置的自动配置类(如 WebMvcAutoConfiguration、DataSourceAutoConfiguration)
最近更新: 9/19/2026, 1:27:08 PM
编程NOTE   |