0

我有以下两个类和 yaml-config:

第一类:

 @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);
    }
...
}

如果行中有@Validated注解 ֎ 1 ֎

然后appProps.subscriber == null in row ֎ 2 ֎. (NPE 出现)

如果行中没有@Validated注解 ֎ 1 ֎

然后appProps.subscriber != null in row ֎ 2 ֎. (按预期工作)

为什么会这样以及如何避免?

4

1 回答 1

1

解决方案如下:

  • 当@ConfigurationProperties 类上没有@Validate 注释时,调用 appProps.subscriber 指的是 SplitterProps 类的实例
  • 当 @ConfigurationProperties 类上有@Validate注释时,SplitterProps 会包装到 Spring 代理中,因此调用 appProps.subscriber是指代理成员

为了处理这种行为,我应该通过 getter执行字段访问。

所以我在 SplitterProps 类中添加了@Getter,现在 appProps.getSubscriber() != null。

于 2020-08-21T13:53:44.660 回答