近日,Spring Boot 2.2.0 版本正式发布,其中一项值得关注的新特性是支持通过构造器进行配置属性的绑定。本文将通过实际示例,探讨这一功能的具体应用场景与优势。

实践示例

以下是一个完整的属性绑定类定义:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

@ConstructorBinding
@ConfigurationProperties(prefix = "tom")
public class TomProperties {

    private final String name;
    private final String sex;
    private final int age;
    private final String country;
    private final Date entryTime;

    public TomProperties(String name,
                         String sex,
                         int age,
                         @DefaultValue("China") String country,
                         @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date entryTime) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.country = country;
        this.entryTime = entryTime;
    }

    // Getter 方法省略...

    @Override
    public String toString() {
        return "TomProperties{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", country='" + country + '\'' +
                ", entryTime=" + entryTime +
                '}';
    }
}

对应的配置文件内容:

tom:
  name: Tom
  sex: man
  age: 18
  entry-time: 2012-12-12 12:00:00

运行后输出的绑定结果:

TomProperties{name='Tom', sex='man', age=18, country='China', entryTime=Wed Dec 12 12:00:00 CST 2012}

@ConstructorBinding 核心特性解析

这项新功能的核心是在原有的 @ConfigurationProperties 注解基础上,增加了 @ConstructorBinding 注解的支持。以下是该注解的关键特性总结:

1. 注入方式优先级
添加 @ConstructorBinding 注解后,系统会优先尝试通过带参数的构造器完成属性注入。只有当类中不存在带参构造器时,才会回退到传统的
Setter 方法注入模式。

2. 构造器使用规范

  • 当注解应用于类级别时,该类必须只包含一个带参数的构造器
  • 若存在多个构造器,可将 @ConstructorBinding 直接标注在需要使用的特定构造器上

3. 不可变对象支持
通过构造器注入,可以将类成员变量声明为 final,从而创建不可变的对象实例。

4. 嵌套类支持
该机制同样适用于内部类的构造器注入场景。

5. 注解协同工作
可以与 @DefaultValue(提供默认值)、@DateTimeFormat(时间格式转换)等注解配合使用。

6. 必要条件
必须与 @ConfigurationProperties@EnableConfigurationProperties 注解组合使用才能生效。

7. 使用限制
不支持通过 @Component@Bean@Import 等方式创建的Bean使用构造器参数绑定。

注解源码简析

查看 @ConstructorBinding 的源码定义:


@Target({ElementType.TYPE, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConstructorBinding {
}

可以看到这是一个标记性注解,不包含任何配置参数,其主要作用就是向Spring Boot框架声明使用构造器绑定的策略。

技术价值

构造器绑定方式为Spring
Boot应用提供了更加灵活和安全的配置注入方案。特别是对于需要创建不可变对象的场景,这种方式能够确保对象在初始化后其状态不会被意外修改,从而提升代码的健壮性和可维护性。同时,通过显式的构造器参数,也使得依赖关系更加清晰明确。