@Validated注解使@ConfigurationProperties类的字段变为null。

huangapple go评论71阅读模式
英文:

@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&lt;@NotNull @Valid Converter&gt; converters;

    @ConstructorBinding
    public SplitterProps(ConnectionParams connectionParams,
                                Map&lt;String, Subscriber&gt; subscribersList,
                                List&lt;Converter&gt; 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&lt;String, Object&gt; 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.

huangapple
  • 本文由 发表于 2020年8月21日 18:08:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63520819.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定