问题描述
创建一个自定义线程池,线程池的参数取自配置值,并在构造函数中进行创建,但是参数值一直为null。代码示例如下:
public class TaskHandler {
private ThreadPoolExecutor pool;
@Value("thread.coreSize")
private int corePoolSize;
@Value("thread.maxSize")
private int maximumPoolSize;
@Value("thread.aliveTime")
private long keepAliveTime;
// ...
public TaskHandler() {
pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// ...
}
}
问题原因
主要原因是,程序会先执行构造函数,然后再为@Value修饰的成员变量注入配置值。因此,执行构造函数的时候,配置项的值一直为null。
解决方案
(1)方式一:构造函数通过传参设置,代码如下:
public TaskHandler(@Value("thread.coreSize") int corePoolSize,
@Value("thread.maxSize") int maximumPoolSize,
@Value("thread.aliveTime") long keepAliveTime) {
pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// ...
}
(2)方式二:通过@Configuration搭配@ConfigurationProperties进行创建,尤其当成员变量比较多的时候,推荐这种方式。代码如下:
@ConfigurationProperties(prefix = "thread")
class ThreadProperties {
private int corePoolSize;
private int maximumPoolSize;
private long keepAliveTime;
// ...
}
@Configuration
@EnableConfigurationProperties(ThreadProperties.class)
class ThreadAutoConfiguration {
@Autowired
private ThreadProperties props;
@Bean
public ThreadPoolExecutor pool() {
ThreadPoolExecutor pool = new ThreadPoolExecutor(props.getCorePoolSize(), props.getMaximumPoolSize(), props.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// ...
return pool;
}
}
其他情况
通过@Value获取不到配置值的其他情况有:
(1)变量使用static或final修饰。
(2)类没有加上@Component(或者@service等)修饰。
(3)类通过new创建实例,而没有通过@Autowired注入。