英文:
@Validated annotation makes field of @ConfigurationProperties class to be null
问题
以下是翻译好的部分:
类 1:
@ConfigurationProperties
@Validated ֎ 1 ֎
public class SplitterProps {
@Valid
public final ConnectionParams connectionParams;
// @Valid
// @NotNull
public final Subscriber subscriber;
public final List<@NotNull @Valid Converter> converters;
@ConstructorBinding
public SplitterProps(ConnectionParams connectionParams,
Map<String, Subscriber> subscribersList,
List<Converter> converters) {
this.connectionParams = connectionParams;
this.subscriber = subscribersList.isEmpty() ?
null :
subscribersList.values().iterator().next();
this.converters = converters;
}
...
}
YAML 配置:
...
subscribersList:
sub1:
kafkaBroker: xxx:9092
topicName: saveTopic
healthCheckTimeout: 10
producerTimeout: 10
...
类 2:
@Configuration(proxyBeanMethods = false)
public class KafkaConfig {
private final Subscriber subscriberProps;
private final Map<String, Object> producerProps;
public KafkaConfig(KafkaProperties kafkaProps,
SplitterProps appProps) {
this.subscriberProps = appProps.subscriber; ֎ 2 ֎
this.producerProps = getProducerProperties(kafkaProps, subscriberProps);
}
...
}
如果在第 ֎ 1 ֎ 行有 @Validated 注解,
则在第 ֎ 2 ֎ 行,appProps.subscriber == null。(导致 NPE 错误)
如果在第 ֎ 1 ֎ 行没有 @Validated 注解,
则在第 ֎ 2 ֎ 行,appProps.subscriber != null。(按预期工作)
为什么会出现这种情况,以及如何避免?
英文:
I have the following two classes and yaml-config:
Class 1:
@ConfigurationProperties
@Validated ֎ 1 ֎
public class SplitterProps {
@Valid
public final ConnectionParams connectionParams;
// @Valid
// @NotNull
public final Subscriber subscriber;
public final List<@NotNull @Valid Converter> converters;
@ConstructorBinding
public SplitterProps(ConnectionParams connectionParams,
Map<String, Subscriber> subscribersList,
List<Converter> converters) {
this.connectionParams = connectionParams;
this.subscriber = subscribersList.isEmpty() ?
null :
subscribersList.values().iterator().next();
this.converters = converters;
}
...
}
YAML-config:
...
subscribersList:
sub1:
kafkaBroker: xxx:9092
topicName: saveTopic
healthCheckTimeout: 10
producerTimeout: 10
...
Class 2:
@Configuration(proxyBeanMethods = false)
public class KafkaConfig {
private final Subscriber subscriberProps;
private final Map<String, Object> producerProps;
public KafkaConfig(KafkaProperties kafkaProps,
SplitterProps appProps) {
this.subscriberProps = appProps.subscriber; ֎ 2 ֎
this.producerProps = getProducerProperties(kafkaProps, subscriberProps);
}
...
}
If there IS @Validated annotation in row ֎ 1 ֎
then appProps.subscriber == null in row ֎ 2 ֎. (NPE arised)
If there is NO @Validated annotation in row ֎ 1 ֎
then appProps.subscriber != null in row ֎ 2 ֎. (works as expected)
Why could it be and how to avoid it?
答案1
得分: 2
解决方案如下:
- 当在@ConfigurationProperties类上没有@Validate注解时,调用appProps.subscriber将引用SplitterProps类的实例。
- 当在@ConfigurationProperties类上有@Validate注解时,SplitterProps会包装成Spring代理,因此调用appProps.subscriber将引用代理成员。
为了处理这种行为,我应该通过getter执行字段访问。
因此,我已经在SplitterProps类上添加了@Getter,现在appProps.getSubscriber() != null。
英文:
Solution is the following:
- when there is no @Validate annotation on @ConfigurationProperties class
then calling appProps.subscriber refers to instance of SplitterProps class. - when there is @Validate annotation on @ConfigurationProperties class
then SplitterProps wraps into Spring proxy so calling appProps.subscriber refers to proxy member.
To handle this behavior I should perform field access via getter.
So I've added @Getter to SplitterProps class and now appProps.getSubscriber() != null.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论