@Value("${save-db.nanchang-batch-size:100}")
private int batchSize;
@Value("${save-db.blocking-queue-size:30000}")
private int blockingQueueSize;
@Value("${save-db.flush-interval:3000}")
private int flushInterval
private BlockingQueue<SmsTask> messageQueue = new LinkedBlockingQueue<>(blockingQueueSize);
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public SmsHandler() {
channelCode = ChannelType.SMS.getCodeEn();
// 启动定时任务,定期执行批处理
log.info("启动短信发送定时任务:{}", flushInterval);
scheduler.scheduleAtFixedRate(this::flushBatch, flushInterval, flushInterval, TimeUnit.MILLISECONDS);
}
问题
确定我的配置正确,但是启动服务的时候始终报这几个参数都是null,哪怕给了默认值都是null,开启debug模式,发现是加载顺序问题,类的字段初始化、构造函数初始化时间点都在@Value之前,所以就有这个问题,解决方案如下:
@Value("${save-db.nanchang-batch-size:100}")
private int batchSize;
@Value("${save-db.blocking-queue-size:30000}")
private int blockingQueueSize;
private BlockingQueue<SmsTask> messageQueue;
@PostConstruct
public void init() {
messageQueue = new LinkedBlockingQueue<>(blockingQueueSize);
}
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public SmsHandler(@Value("${save-db.flush-interval:3000}") int flushInterval) {
log.info("启动短信发送定时任务:{}", flushInterval);
scheduler.scheduleAtFixedRate(this::flushBatch, flushInterval, flushInterval, TimeUnit.MILLISECONDS);
}
总结
Spring的依赖注入机制决定了@Value的注入发生在bean的构造函数执行之后。因此,在构造函数或字段初始化时直接使用@Value注入的值会导致null值。通过将初始化逻辑放到@PostConstruct方法中、使用构造函数注入,或者使用@ConfigurationProperties绑定配置属性,可以有效解决这个问题。