SpringBoot松散绑定/宽松绑定(Relaxed Binding)的实现
作者:五月天的尾巴
一、前言
在 Java 的配置文件中(如 .properties 和 .yml/.yaml),你看到驼峰命名(如 myProperty)和中划线命名(如 my-property)同时有效,主要是因为 Spring Boot 的“宽松绑定”(Relaxed Binding)策略。
以mybatis的属性配置为例
application.yml文件
# mybatis属性配置 mybatis: configuration: map-underscore-to-camel-case: true # 开启下划线转驼峰的映射
application.properties文件
# mybatis属性配置 mybatis.configuration.mapUnderscoreToCamelCase: true # 开启下划线转驼峰的映射
二、宽松绑定
2.1、何为宽松绑定
简单来说,宽松绑定是 Spring Boot 提供的一种智能属性绑定机制。它允许你在配置属性(如 application.properties、application.yml、环境变量、命令行参数)中使用多种不同格式的名称,Spring Boot 都能自动将它们匹配到你的 @ConfigurationProperties
类或 Bean
的对应字段上。
Spring Boot 1.x 版本已初步支持宽松绑定,Spring Boot 2.x 版本进一步强化了宽松绑定的规范性和一致性。新项目建议直接采用 Spring Boot 2.x + @ConfigurationProperties 以保障兼容性。
- @ConfigurationProperties 成为官方推荐方式 :明确仅通过此注解支持完整的宽松绑定规则(如前缀命名需符合 kebab-case 格式)。
- @Value 的局限性被固化: 虽然部分简单场景下 @Value 可能兼容宽松格式(如环境变量转小写匹配),但官方文档始终强调其不支持正式宽松绑定,未来版本可能调整此行为。
2.2、宽松绑定的规则
Spring Boot 支持以下几种属性命名格式的自动转换:
- 驼峰命名法(myProperty)
- 短横线命名法(my-property)
- 下划线命名法(my_property)
- 大写下划线命名法(MY_PROPERTY)
2.3、宽松绑定规则详解
Spring Boot 在匹配时,会将配置源(文件、环境变量等)中的属性名和 Java Bean 属性名都进行规范化处理:
- 将所有字符转换为小写。
- 移除所有分隔符(-, _, 空格)。
- 比较规范化后的结果。
示例:
Java Bean 属性名 | 有效的配置文件/YAML 属性名示例 | 规范化后结果 (小写, 无分隔符) |
---|---|---|
userName | userName (驼峰) | username |
user-name (中划线 - 推荐) | username | |
user_name (下划线) | username | |
USER_NAME (环境变量风格 - 大写+下划线) | username | |
server.port | server.port (点分隔) | server.port (点保留) |
server-port (不推荐,但宽松绑定可能允许) | serverport (可能出错!) |
重要提示: 对于带 . 的层级属性(如 server.port),使用中划线替代点(server-port)通常不是好主意,也不推荐。 虽然宽松绑定在简单情况下可能“碰巧”工作(规范化后 serverport 与 server.port 的规范化形式 server.port 不同),但它破坏了属性的层次结构,可能导致意外的绑定结果或错误。点 . 是表示配置树层次结构的标准和推荐方式。
总结:
松散绑定就是在进行匹配时,配置中的名称要去掉中划线和下划线后,忽略大小写的情况下去与java代码中的属性名进行忽略大小写的等值匹配
2.4、优先级规则
如果同一属性以不同格式多次配置,Spring Boot 按以下优先级绑定:
- 精确匹配(字段名与配置名完全一致)。
- 短横线命名法。
- 下划线命名法。
- 大写下划线命名法。
2.5、注意事项
在SpringBoot官方文档中有几个注意点:
- 属性必须要有getter、setter方法;
- 如果属性的类型是集合,要确保集合是不可变的;
- 如果使用Lombok自动生成getter/setter方法,一定不要生成对应的任何构造函数,因为Spring IOC容器会自动使用它来实例化对象。
- 使用JavaBean属性绑定的方式只针对标准 Java Bean 属性,不支持对静态属性的绑定。
- 前缀匹配: @ConfigurationProperties 的 prefix 也支持宽松绑定。例如,prefix = “my-app” 可以匹配 myApp、my_app 等。
- 严格模式: 可以通过
spring.boot.configurationprocessor.strict
启用严格模式,禁用宽松绑定。
三、宽松绑定实例
3.1、@ConfigurationProperties注解与宽松绑定
application.yml
user: userName: 张三 # 驼峰命名 user-age: 11 # 中划线 user_class: 三年级二班 # 下划线 USER_SEX: 男 # 大写+下划线
UserConfig.java
package com.demo.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "user") @Data public class UserConfig { private String userName; private int userAge; private String userClass; private String userSex; }
TestController.java
package com.demo.controller; import com.demo.config.UserConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "test") public class TestController { @Autowired UserConfig userConfig; @Value("${user.userage}") private String userage; @GetMapping("") public String test(){ System.out.println(userConfig); return userConfig.toString(); } }
四、其他问题
4.1、Spring Boot Configuration Annotation Processor not configured
问题描述: 当我们使用@ConfigurationProperties注解进行属性注入时,配置类上面可能会显示Spring Boot Configuration Annotation Processor not configured
解决方法:
在pom.xml中引入一下依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
该依赖的作用,简单来说就是为自定义的配置类生成元数据信息。然后报错问题解决,文件能够正常使用。
五、总结
注意:
- ConfigurationProperties的prefix的值必须是短横线隔开式,如demo.relaxed-binding
- @ConfigurationProperties注解支持全量的属性 宽松绑定方式;而@Value只推荐使用标准的kebab-case方式(仅使用小写字母和-),例如:@Value(“{demo.item-price}”)可以提取demo.item-price和demo.itemPrice。
- 松散绑定就是在进行匹配时,配置中的名称要去掉中划线和下划线后,忽略大小写的情况下去与java代码中的属性名进行忽略大小写的等值匹配
到此这篇关于SpringBoot松散绑定/宽松绑定(Relaxed Binding)的实现的文章就介绍到这了,更多相关SpringBoot松散绑定/宽松绑定内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!