Spring Boot如何让ConfigurationProperties配置类可选并初始化为null
我有一个使用application.yml配置的Spring Boot应用,配置片段如下:
... rmq: host: "host" port: 5672 ...
对应的配置类代码如下:
@AllArgsConstructor class ApplicationConfig { private RabbitConfig rabbitConfig; } @ConfigurationProperties(prefix = "rmq") class RabbitConfig { @NotNull private String host; @NotNull private Integer port; }
现在的问题是:rmq配置节点是可选的,我希望当application.yml中不存在该节点时,rabbitConfig字段能初始化为null。但实际删除该节点后,应用启动会报错“rmq.host不存在”,请问如何让Spring Boot实现这个需求?
要实现可选配置节点的需求,需要从三个方面调整:
1. 移除RabbitConfig中的@NotNull约束
@NotNull注解会强制Spring Boot在绑定配置时校验字段非空,当rmq节点不存在时,host和port无法被赋值,直接触发校验错误。把这两个注解去掉即可:
@ConfigurationProperties(prefix = "rmq") class RabbitConfig { private String host; private Integer port; }
2. 用条件注解控制RabbitConfig的实例化
默认情况下,@ConfigurationProperties绑定的Bean会被强制创建,哪怕对应配置节点不存在。需要通过@ConditionalOnProperty注解设置创建条件,只有当rmq相关配置存在时才实例化这个Bean:
@ConfigurationProperties(prefix = "rmq") // 只有当rmq.host和rmq.port都存在时才创建Bean @ConditionalOnProperty(prefix = "rmq", name = {"host", "port"}, matchIfMissing = false) class RabbitConfig { private String host; private Integer port; }
如果只要rmq根节点存在就允许创建(不管子字段是否齐全,根据业务场景选择),可以简化为:
@ConfigurationProperties(prefix = "rmq") @ConditionalOnProperty(prefix = "rmq", name = "*", matchIfMissing = false) class RabbitConfig { private String host; private Integer port; }
3. 调整ApplicationConfig的依赖注入逻辑
因为RabbitConfig现在是可选Bean,直接用@AllArgsConstructor构造器注入会导致Spring找不到Bean报错,需要改成可选注入:
@Component class ApplicationConfig { private final RabbitConfig rabbitConfig; // 构造器参数标记为可选,不存在时传入null public ApplicationConfig(@Nullable RabbitConfig rabbitConfig) { this.rabbitConfig = rabbitConfig; } }
也可以用字段注入的方式(不推荐用于新代码,但适配现有代码时可用):
@Component class ApplicationConfig { @Autowired(required = false) private RabbitConfig rabbitConfig; }
调整完成后,当application.yml中没有rmq节点时,RabbitConfig不会被实例化,ApplicationConfig中的rabbitConfig字段就会是null;当存在rmq节点时,正常完成配置绑定并注入Bean。
内容的提问来源于stack exchange,提问作者Haster

