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
- 所有在配置文件中能配置的属性都是在xxxxProperties类中封装的;配置文件能配置什么就可以参照某个功能对应的这个属性类。
9.2.1字符编码配置
以2.7.6的ServerProperties中字符编码的配置为例。
核心结论
Spring Boot 2.7.6 的字符编码配置,本质是通过 Encoding 类封装默认值 / 配置值,再通过 ServerProperties 关联配置文件,最终由 HttpEncodingAutoConfiguration 注册过滤器生效------ 默认值 "在 Encoding 里设定",正是框架设计的核心:Encoding 是编码配置的 "容器",默认值、配置文件值都存在这里,而非直接写在 properties 文件里。
一、三层关联逻辑(从配置到生效)
先理清 Encoding → ServerProperties → HttpEncodingAutoConfiguration 的关系,就懂了 "编码在哪设、怎么生效":
- Encoding 类:编码配置的 "数据载体",存储编码相关的默认值、从配置文件读取的值(如字符集、是否强制编码);
- ServerProperties 类:作为 "配置枢纽",通过内部 Servlet 子类关联 Encoding,并绑定配置文件 server.servlet.encoding 前缀;
- 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 应用;
- 编码生效的完整流程:
- 启动时,@EableConfigurationProperties 启用 ServerProperties,绑定配置文件 server.servlet.encoding 配置;
- 构造器注入 ServerProperties,提取 servlet.encoding 配置(即 Encoding 实例);
- @Bean 注解注册 CharacterEncodingFilter,过滤器的编码、强制编码规则,全部取自 Encoding 实例;
- 过滤器生效,对所有请求 / 响应进行编码处理(默认 UTF-8,可通过配置文件修改)。
三、关键疑问解答
- "字符编码不是在 properties 文件里设置的,是在 Encoding 里设定的"------ 为什么?
答:Encoding 是编码配置的 "Java 载体",默认值确实在 Encoding 里硬编码(UTF-8);而 properties/yaml 文件是 "用户自定义配置的入口",作用是覆盖 Encoding 里的默认值。两者的关系:Encoding 存 "默认值",配置文件存 "自定义值",最终生效的是 "自定义值(若有)→ 默认值(若无)"。