ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot读取配置的一次实践

2022-07-31 10:03:06  阅读:213  来源: 互联网

标签:读取 SpringBoot messageQueue 实践 private properties timeout public 属性


我有这样一个Service,我需要在外面注入queueSizetimeout这两个属性:

@Service
@Slf4j
public class BlockingQueueMessageService implements MessageService, InitializingBean {

    private Duration timeout;
    private Integer queueSize;

    private BlockingQueue<SMSMessage> messageQueue;

}

直接在本类使用@ConfigurationProperties

最初,我直接在本类使用的@ConfigurationProperties

@Service
@Slf4j
@ConfigurationProperties(prefix="blocking-message-service")
public class BlockingQueueMessageService implements MessageService, InitializingBean {

    private BlockingQueue<SMSMessage> messageQueue;
    private Duration timeout;

    private BlockingQueue<SMSMessage> messageQueue;

并在配置文件中指定:

blocking-message-service:
  queue-size: 10
  timeout: 1000

不过我还没有测试就陷入了疑惑,本类中除了这两个需要注入的属性之外,还有一个BlockingQueue,Spring会如何处理它?如果外部通过配置文件也配置了一个叫messageQueue的属性呢?会不会报错?

所以,我感觉上面这种方式非常不优雅,所以我立即替换了实现方式

提供单独的属性配置类

我提供了一个单独的属性配置类,并且把它声明为了@Component,然后再使用@ConfigurationProperties读取配置文件

@Data
@Component
@ConfigurationProperties(prefix = "blocking-message-service")
public class BlockingQueueMessageServiceProperties {
    private Integer queueSize;
    @DurationUnit(ChronoUnit.MILLIS)
    private Duration timeout;
}

然后在原先的类中,我通过@Autowired注入这个属性配置类:

@Service
@Slf4j
public class BlockingQueueMessageService implements MessageService, InitializingBean {

    @Autowired
    private BlockingQueueMessageServiceProperties properties;

    private BlockingQueue<SMSMessage> messageQueue;
}

这样,就不会产生疑惑了,messageQueue这个属性无论如何都是安全的。

使用自动注入的配置值进行初始化

@Autowired注入发生在Bean的属性设置阶段,所以如果在上面的代码中直接使用属性值来初始化messageQueue,就会报空指针异常,因为properties属性还没有被注入

@Autowired
private BlockingQueueMessageServiceProperties properties;

// !!不要这样做!! 在实例化阶段`properties`还没被注入,它等于null!!
private BlockingQueue<SMSMessage> messageQueue = new LinkedBlockingQueue(properties.getQueueSize());

我通过实现InitializingBeanafterPropertiesSet方法,在属性设置阶段之后进行初始化,这时properties已经被安全的注入:

@Service
@Slf4j
public class BlockingQueueMessageService implements MessageService, InitializingBean {

    // ...

    @Override
    public void afterPropertiesSet() throws Exception {
        messageQueue = new LinkedBlockingQueue<>(properties.getQueueSize());
    }

}

避免空值

如果在配置文件中没有给定一个值的话,你可以通过给属性直接赋值来给它一个默认值,否则,对应的属性有可能有为null的风险:

blocking-message-service:
  # queue-size: 10
  timeout: 1000
@Data
@Component
@ConfigurationProperties(prefix = "blocking-message-service")
public class BlockingQueueMessageServiceProperties {
    // 这个赋值发生在实例化阶段,`@ConfigurationProperties`中如果有对应的值会覆盖这个设置
    private Integer queueSize = 1024;
    @DurationUnit(ChronoUnit.MILLIS)
    private Duration timeout = Duration.ofMillis(1000);
}

如果不想这样设置默认值,你还可以提供一个这样的工具方法:

public static <T> T getOrDefault(Supplier<T> supplier, T defaultValue) {
    T t = supplier.get();
    return t == null ? defaultValue : t;
}

然后,在读取值时可以使用这个方法:

timeout = getOrDefault(properties::getTimeout, Duration.ofMillis(1000));

标签:读取,SpringBoot,messageQueue,实践,private,properties,timeout,public,属性
来源: https://www.cnblogs.com/lilpig/p/16536489.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有