SpringBoot自动配置类

9 自动配置类

9.1 xxxAutoConfiguration

以HttpEncodingAutoConfiguration为例解释

2.7.6的配置类所在的文件无法直接点进去,可以Ctrl+N 直接搜索全类名,即可找到对应的文件,或者是在下图这个位置找到全类名对应的包名

下面这个代码是2.7.6的代码

java 复制代码
// 1. @AutoConfiguration:2.7+ 版本新增,替代旧版 @Configuration 标记自动配置类
// 作用:明确当前是 Spring Boot 自动配置类,优先级高于普通 @Configuration 类,确保自动配置流程优先执行
// 自动装配影响:必须有此注解,否则无法被 Spring Boot 自动配置机制扫描加载
@AutoConfiguration 

// 2. @EnableConfigurationProperties({ServerProperties.class}):2.7.6 版本变更(替代旧版 HttpEncodingProperties)
// 作用:① 启用 ServerProperties 类的 @ConfigurationProperties 功能,使其能读取 application.yaml 中 "server." 前缀配置;
//      ② 将 ServerProperties 实例(已绑定配置值)注册到容器,供构造器注入
// 自动装配影响:无此注解,下面的 properties 参数无法获取值,配置类初始化失败
@EnableConfigurationProperties({ServerProperties.class}) 

// 3. @ConditionalOnWebApplication(type = Type.SERVLET):Spring 条件注解(2.7.6 明确 Web 类型)
// 核心作用:判断当前应用是否为「Servlet 类型 Web 应用」(即传统 Spring MVC 应用,区别于 WebFlux 响应式应用)
// 判断标准:类路径中存在 Servlet 相关类(如 javax.servlet.Servlet)、容器是 Servlet 容器(如 Tomcat)
// 生效结果:
// - 满足(Servlet Web 应用):配置类继续往下执行;
// - 不满足(纯 Java 项目/ WebFlux 项目):整个配置类失效,不会注册任何 Bean(乱码过滤器、自定义器都不加载)
// 自动装配影响:非 Servlet Web 场景,自动装配直接跳过
@ConditionalOnWebApplication(
    type = Type.SERVLET
)

// 4. @ConditionalOnClass({CharacterEncodingFilter.class}):Spring 条件注解(核心依赖判断)
// 核心作用:判断当前项目类路径中,是否存在 CharacterEncodingFilter 类(Spring MVC 内置乱码处理过滤器)
// 判断标准:项目是否引入 spring-webmvc 依赖(该类在 spring-webmvc.jar 中,引入 spring-boot-starter-web 会自动传递)
// 生效结果:
// - 满足(存在该类):配置类继续执行;
// - 不满足(未引入 web 依赖):整个配置类失效,乱码过滤器无法自动装配
// 自动装配影响:缺少依赖时,自动装配失败(需手动引入 spring-boot-starter-web)
@ConditionalOnClass({CharacterEncodingFilter.class})

//5. @ConditionalOnProperty(prefix = "server.servlet.encoding", value = {"enabled"}, matchIfMissing = true):Spring 条件注解(配置开关判断)
// 核心作用:判断 application.yaml 中「server.servlet.encoding.enabled」配置项的状态(2.7.6 配置前缀变更,旧版是 spring.http.encoding)
// 判断标准:
// - 配置了「server.servlet.encoding.enabled=true」→ 满足;
// - 配置了「server.servlet.encoding.enabled=false」→ 不满足;
// - 未配置该属性 → 因 matchIfMissing=true,默认满足
// 生效结果:
// - 满足:配置类继续执行,乱码过滤器会被注册;
// - 不满足:配置类失效,乱码过滤器不自动装配
// 自动装配影响:默认自动生效,可通过配置手动关闭(体现「配置大于约定」)
//这个prefix就是yml配置文件写的那些值,写的时候 idea会提示默认值
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)

// 核心配置类:处理 Servlet Web 应用的 HTTP 编码自动配置
// 生效前提:上面 3、4、5 三个 Conditional 注解必须「同时满足」,否则整个类失效
public class HttpEncodingAutoConfiguration {

    // 6. 成员变量properties:从 ServerProperties 中获取 servlet.encoding 相关配置(2.7.6 整合后的属性存储)
    private final Encoding properties;

    // 7. 有参构造器:注入 ServerProperties 实例,提取 encoding 配置
    // 作用:Spring 自动从容器中获取 ServerProperties,通过 getServlet().getEncoding() 拿到编码配置
    // 自动装配影响:获取不到 ServerProperties 会报错(需 @EnableConfigurationProperties 注解)
    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

    // 8. @Bean:向容器注册 CharacterEncodingFilter Bean(乱码处理核心组件)
    // 自动装配影响:无此注解,过滤器无法被注册到容器
    @Bean

    // 9. @ConditionalOnMissingBean:Spring 条件注解(用户优先级判断)
    // 核心作用:判断容器中是否「已经存在 CharacterEncodingFilter 类型的 Bean」(包括用户手动注册的)
    // 判断标准:容器中无该类型 Bean → 满足;有则不满足
    // 生效结果:
    // - 满足(无用户自定义 Bean):当前 @Bean 生效,注册 Spring Boot 默认的乱码过滤器;
    // - 不满足(有用户自定义 Bean):当前 @Bean 失效,优先使用用户注册的过滤器
    // 自动装配影响:体现「用户配置优先于自动配置」,避免重复注册
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name()); // 编码格式(默认 UTF-8,可通过 server.servlet.encoding.charset 配置)
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST)); // 强制请求编码(默认跟随配置)
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE)); // 强制响应编码(默认跟随配置)
        return filter;
    }

    // 10. @Bean:注册 LocaleCharsetMappingsCustomizer Bean(用于自定义 Tomcat 容器的语言-字符集映射)
    @Bean
    public HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
        return new HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer(this.properties);
    }

    // 内部静态类:Web 服务器工厂自定义器,用于配置容器的语言-字符集映射
    static class LocaleCharsetMappingsCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
        private final Encoding properties;

        LocaleCharsetMappingsCustomizer(Encoding properties) {
            this.properties = properties;
        }

        public void customize(ConfigurableServletWebServerFactory factory) {
            // 若配置了 server.servlet.encoding.mapping(语言-字符集映射),则应用到容器
            if (this.properties.getMapping() != null) {
                factory.setLocaleCharsetMappings(this.properties.getMapping());
            }
        }

        public int getOrder() {
            return 0; // 执行优先级:最高(确保映射配置先于其他容器配置生效)
        }
    }
}

问 1:2.7.6 中,HttpEncodingAutoConfiguration 生效的前提是什么?
答:三个条件必须同时满足:① 是 Servlet 类型 Web 应用;② 引入 web 依赖(类路径有 CharacterEncodingFilter);③ 未关闭 server.servlet.encoding.enabled 配置(默认开启)。
问 2:如果我手动注册了 CharacterEncodingFilter,自动配置还会生效吗?
答:不会。@ConditionalOnMissingBean 会检测到容器中已有该 Bean,默认过滤器的 @Bean 会失效,优先使用用户自定义的过滤器。
问 3:如何手动关闭这个自动配置类?
答:两种方式:① 配置文件中添加 server.servlet.encoding.enabled=false;② 主程序类用 @SpringBootApplication(exclude = HttpEncodingAutoConfiguration.class) 排除。
注:在配置文件中加入debug=true属性,启动项目后,可以在控制台看到那些自动配置类生效;
但是其他旧版本中的不是这个。

9.2 xxxProperties

  1. 所有在配置文件中能配置的属性都是在xxxxProperties类中封装的;配置文件能配置什么就可以参照某个功能对应的这个属性类。

9.2.1字符编码配置

以2.7.6的ServerProperties中字符编码的配置为例。

核心结论

Spring Boot 2.7.6 的字符编码配置,本质是通过 Encoding 类封装默认值 / 配置值,再通过 ServerProperties 关联配置文件,最终由 HttpEncodingAutoConfiguration 注册过滤器生效------ 默认值 "在 Encoding 里设定",正是框架设计的核心:Encoding 是编码配置的 "容器",默认值、配置文件值都存在这里,而非直接写在 properties 文件里。

一、三层关联逻辑(从配置到生效)

先理清 Encoding → ServerProperties → HttpEncodingAutoConfiguration 的关系,就懂了 "编码在哪设、怎么生效":

  1. Encoding 类:编码配置的 "数据载体",存储编码相关的默认值、从配置文件读取的值(如字符集、是否强制编码);
  2. ServerProperties 类:作为 "配置枢纽",通过内部 Servlet 子类关联 Encoding,并绑定配置文件 server.servlet.encoding 前缀;
  3. HttpEncodingAutoConfiguration 类:自动配置类,注入 ServerProperties 后提取 Encoding 配置,注册 CharacterEncodingFilter 过滤器,让编码配置生效。
二、逐类解析(重点讲编码相关核心逻辑)

Encoding 类:编码配置的 "容器"(默认值 + 配置值都在这)

java 复制代码
package org.springframework.boot.web.servlet.server;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Map;

public class Encoding {
    public static final Charset DEFAULT_CHARSET; // 静态常量:默认字符集
    private Charset charset; // 字符集(默认UTF-8,可通过配置文件覆盖)
    private Boolean force; // 是否强制所有编码(请求+响应)
    private Boolean forceRequest; // 是否强制请求编码
    private Boolean forceResponse; // 是否强制响应编码
    private Map<Locale, Charset> mapping; // 语言-字符集映射(如中文→GBK)

    // 构造器:初始化默认字符集
    public Encoding() {
        this.charset = DEFAULT_CHARSET; // 默认值:UTF-8
    }

    // 核心方法:判断是否强制指定类型(请求/响应)的编码,这个方法的具体调用在HttpEncodingAutoConfiguration里的CharacterEncodingFilter方法
    //我会传入不同的类型(请求/响应),然后根据类型的不同,设置编码
    public boolean shouldForce(Encoding.Type type) {
        // 步骤1:先查"单独配置"(针对请求/响应的专用开关)
        Boolean force = type != Encoding.Type.REQUEST ? this.forceResponse : this.forceRequest;
    
        // 步骤2:如果单独配置为null(未设置),则用"全局配置"
        if (force == null) {
            force = this.force; 
        }
    
        // 步骤3:如果全局配置也为null(未设置),则用"默认规则"
        if (force == null) {
            force = type == Encoding.Type.REQUEST; // 请求默认true(强制请求编码),响应默认false(不强制响应编码)
        }
    
        return force;
    }

    // 静态代码块:初始化默认字符集为UTF-8(硬编码的默认值)
    static {
        DEFAULT_CHARSET = StandardCharsets.UTF_8;
    }

    // 枚举:区分请求/响应编码类型
    public static enum Type {
        REQUEST, RESPONSE;
    }

    // getter/setter:用于绑定配置文件值(省略,核心是charset、force等属性)
}
  • 核心作用:专门存储编码相关的配置,相当于 "编码配置的 JavaBean";
  • 默认值来源:
    • 字符集:DEFAULT_CHARSET = StandardCharsets.UTF_8(静态代码块硬编码);
    • 强制编码:默认只强制请求编码(shouldForce 方法逻辑);
  • 配置值来源:通过 ServerProperties 的 @ConfigurationProperties 注解,读取 application.yaml 中 server.servlet.encoding 前缀的配置(如 server.servlet.encoding.charset=GBK),覆盖默认值。
  • 优先级公式:forceRequest/forceResponse(单独配置) > force(全局配置) > 默认值(请求true/ 响应false);
    ServerProperties 类:编码配置的 "枢纽"(关联配置文件和 Encoding)
java 复制代码
package org.springframework.boot.autoconfigure.web;

// 关键注解:绑定配置文件中 "server." 前缀的配置
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
    // 内部静态类:封装 Servlet 相关配置(包括编码)
    public static class Servlet {
        // 核心:关联 Encoding 类(@NestedConfigurationProperty 表示嵌套配置)
        @NestedConfigurationProperty
        private final Encoding encoding = new Encoding();

        // getter:供 HttpEncodingAutoConfiguration 提取编码配置
        public Encoding getEncoding() {
            return this.encoding;
        }
    }

    // Servlet 实例(初始化时会创建内部的 Encoding 实例)
    private final ServerProperties.Servlet servlet;

    // 构造器:初始化 Servlet 实例(进而初始化 Encoding 实例)
    public ServerProperties() {
        this.servlet = new ServerProperties.Servlet();
        // 其他属性初始化...
    }

    // getter:供 HttpEncodingAutoConfiguration 注入后获取 Servlet 配置
    public ServerProperties.Servlet getServlet() {
        return this.servlet;
    }

    // 其他服务器配置(端口、SSL等,省略)
}
  • 核心作用:作为 "配置枢纽",一边绑定配置文件 server. 前缀,一边通过内部 Servlet 类关联 Encoding;
  • 编码配置的绑定逻辑:
    • 当你在 application.yaml 写 server.servlet.encoding.charset=GBK 时,@ConfigurationProperties 会自动将该值注入到 Servlet 类的 encoding 属性中;
    • 若不配置,encoding 会使用自身构造器的默认值(UTF-8);
  • 关键注解:@NestedConfigurationProperty 表示 encoding 是嵌套配置,允许配置文件用 server.servlet.encoding.xxx 的层级格式。
    HttpEncodingAutoConfiguration 类:编码配置的 "生效器"(注册过滤器)
java 复制代码
package org.springframework.boot.autoconfigure.web.servlet;

@AutoConfiguration // 2.7+ 自动配置类标识
@EnableConfigurationProperties({ServerProperties.class}) // 启用 ServerProperties 的配置绑定
@ConditionalOnWebApplication(type = Type.SERVLET) // 仅 Servlet Web 应用生效
@ConditionalOnClass({CharacterEncodingFilter.class}) // 存在乱码过滤器类才生效
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = {"enabled"}, matchIfMissing = true) // 默认启用
public class HttpEncodingAutoConfiguration {
    private final Encoding properties; // 编码配置(从 ServerProperties 提取)

    // 构造器:注入 ServerProperties,提取 Servlet 中的 Encoding 配置
    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

    // 注册乱码过滤器 Bean(核心生效逻辑)
    @Bean
    @ConditionalOnMissingBean // 容器中没有该 Bean 才注册(用户优先)
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name()); // 用 Encoding 的字符集(默认UTF-8或配置值)
        // 用 Encoding 的强制编码配置(默认强制请求编码)
        filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
        return filter;
    }

    // 其他Bean(语言-字符集映射自定义器,省略)
}
  • 核心作用:将 Encoding 中的配置(默认值 / 配置值),通过注册 CharacterEncodingFilter 过滤器,应用到整个 Web 应用;
  • 编码生效的完整流程:
  1. 启动时,@EableConfigurationProperties 启用 ServerProperties,绑定配置文件 server.servlet.encoding 配置;
  2. 构造器注入 ServerProperties,提取 servlet.encoding 配置(即 Encoding 实例);
  3. @Bean 注解注册 CharacterEncodingFilter,过滤器的编码、强制编码规则,全部取自 Encoding 实例;
  4. 过滤器生效,对所有请求 / 响应进行编码处理(默认 UTF-8,可通过配置文件修改)。
三、关键疑问解答
  1. "字符编码不是在 properties 文件里设置的,是在 Encoding 里设定的"------ 为什么?
    答:Encoding 是编码配置的 "Java 载体",默认值确实在 Encoding 里硬编码(UTF-8);而 properties/yaml 文件是 "用户自定义配置的入口",作用是覆盖 Encoding 里的默认值。两者的关系:Encoding 存 "默认值",配置文件存 "自定义值",最终生效的是 "自定义值(若有)→ 默认值(若无)"。
相关推荐
q***78372 小时前
Spring Boot 3.X:Unable to connect to Redis错误记录
spring boot·redis·后端
甜鲸鱼2 小时前
Java与MySQL中的枚举(Enum)
java·mysql
xxxxxxllllllshi2 小时前
【LeetCode Hot100----14-贪心算法(01-05),包含多种方法,详细思路与代码,让你一篇文章看懂所有!】
java·数据结构·算法·leetcode·贪心算法
t***26592 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
pengzhuofan2 小时前
Sentinel 服务保护
java·微服务·sentinel
6***37942 小时前
Java安全
java·开发语言·安全
豐儀麟阁贵3 小时前
8.1 异常概述
java·开发语言
qq_12498707533 小时前
基于springboot的疾病预防系统的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·毕业设计
麦烤楽鸡翅3 小时前
简单迭代法求单根的近似值
java·c++·python·数据分析·c·数值分析