前言
前面寫過一個Springboot學習筆記(一)-線程池的簡化及使用,發現有個缺陷,打個比方,我這個線程池寫在一個公用服務中,各項參數都定死了,現在有兩個服務要調用它,一個服務的線程數通常很多,而另一個則很少,那么線程多的服務會感覺這個線程池小,另一個又覺得浪費資源,這樣很不靈活,所以希望將這個線程池被引用的時候可以自定義配置。比如在配置文件中寫下線程池的核心線程數,最大線程數等等,根據不同的需要配置不同的參數。
實現
思路
前面學過【轉】Spring Boot干貨系列:(二)配置文件解析和條件化注入Springboot學習筆記(五)-條件化注入,有了這個基礎,就可以寫一個配置映射類,同時定義一個自動配置類,將配置映射類中的屬性拷貝過來。
實現
配置映射類
ThreadPoolProperties:
@ConfigurationProperties(prefix = "thread", ignoreUnknownFields = false)
public class ThreadPoolProperties {
private int corePoolSize;
private int maxPoolSize;
private int queueCapacity;
private String threadNamePrefix;
private RejectedExecutionHandler rejectedExecutionHandler;
private boolean waitForTasksToCompleteOnShutdown;
public int getCorePoolSize() {
return corePoolSize;
}
public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getQueueCapacity() {
return queueCapacity;
}
public void setQueueCapacity(int queueCapacity) {
this.queueCapacity = queueCapacity;
}
public String getThreadNamePrefix() {
return threadNamePrefix = Optional.ofNullable(threadNamePrefix).orElse("");
}
public void setThreadNamePrefix(String threadNamePrefix) {
if (threadNamePrefix == null || "".equals(threadNamePrefix)) {
this.threadNamePrefix = "default-thread-pool";
return;
}
if (!threadNamePrefix.endsWith("-")) {
this.threadNamePrefix = threadNamePrefix + "-";
return;
}
this.threadNamePrefix = threadNamePrefix;
}
public RejectedExecutionHandler getRejectedExecutionHandler() {
return rejectedExecutionHandler;
}
public void setRejectedExecutionHandler(int rejectedExecutionHandler) {
switch (rejectedExecutionHandler) {
case 1:
this.rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
break;
case 2:
this.rejectedExecutionHandler = new ThreadPoolExecutor.DiscardOldestPolicy();
break;
case 3:
this.rejectedExecutionHandler = new ThreadPoolExecutor.DiscardPolicy();
break;
default:
this.rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();
break;
}
}
public boolean isWaitForTasksToCompleteOnShutdown() {
return waitForTasksToCompleteOnShutdown;
}
public void setWaitForTasksToCompleteOnShutdown(boolean waitForTasksToCompleteOnShutdown) {
this.waitForTasksToCompleteOnShutdown = waitForTasksToCompleteOnShutdown;
}
}
自動配置類
ThreadPoolAutoConfiguration:
@Configuration
@EnableConfigurationProperties(ThreadPoolProperties.class)
@ConditionalOnProperty(name = "thread.corePoolSize")
public class ThreadPoolAutoConfiguration {
private final ThreadPoolProperties threadPoolProperties;
@Autowired
public ThreadPoolAutoConfiguration(ThreadPoolProperties threadPoolProperties) {
this.threadPoolProperties = threadPoolProperties;
}
@Bean
@ConditionalOnMissingBean(ThreadPoolTaskExecutor.class)
public ThreadPoolTaskExecutor taskService() {
ThreadPoolTaskExecutor service = new ThreadPoolTaskExecutor();
BeanUtils.copyProperties(threadPoolProperties, service);
return service;
}
}
配置文件
thread.corePoolSize=4
thread.maxPoolSize=5
thread.queueCapacity=20
thread.threadNamePrefix=hello
thread.rejectedExecutionHandler=1
thread.waitForTasksToCompleteOnShutdown=true
這時有個問題,自動配置有兩種方式,一種是在啟動時直接加載,另外一種是定義一個開關,一般是定義一個名字有意義的注解,當有這個注解的時候再加載和注入自動配置。
啟動直接加載
啟動加載比較簡單,仿照官方做,就是在配置根目錄下定義一個spring.factories文件,它是用來在啟動時讀取的,找到對應的配置類則直接加載注入,格式如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yan.thread.pool.starter.config.ThreadPoolAutoConfiguration
使用開關加載
定義一個開關注解,就叫EnableThreadPool,通過在其上標注@Import(ThreadPoolImportSelector.class)來注入自動配置類ThreadPoolAutoConfiguration。
ThreadPoolImportSelector:
public class ThreadPoolImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{ThreadPoolAutoConfiguration.class.getName()};
}
}
EnableThreadPool:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ThreadPoolImportSelector.class)
public @interface EnableThreadPool {
}
屬性文件自動提示
一般在我們開發中,屬性文件會產生一個自動提示,這個自定義提示也可以把我們的配置類添加到提示中。
真正起作用的是META-INF/spring-configuration-metadata.json文件,springboot為我們提供了便捷方式,可以自動生成此文件,步驟如下:
引入jar包
dependencies {
compile "org.springframework.boot:spring-boot-configuration-processor"
}
在idea設置中搜索Annotation Processors,接下來勾住Enable annonation processing就完成了。

編譯后即可看到自動生成的spring-configuration-metadata.json。
注
有些人習慣叫***-starter,並把它單獨抽成一個服務,打成jar包供外部工程使用,我還是習慣叫配置化注入。
