持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
前言
大概在一个多月前,我参加面试,一个身穿格子衫牛仔裤大概三十多岁的中年男人缓步走来。
先做个自我介绍吧
面试官你好,我叫。。。我巴拉巴拉介绍完。
你了解springboot的自动装配吧。
我当然说了解喽。
那你写过starter么,怎么写的?
我当然说我不知道啦。那是个什么东西,我怎么会写。。。
starter是个啥
我们可以把starter看成一个模块。他整合了模块所需要的依赖和自动化配置模块内的bean。只需要依赖这个starter,Spring Boot就能自动扫描并加载相应的模块。
给他一个总结吧
- 整合了所需依赖库
- 提供自动配置类对模块内的Bean进行自动装配
- 提供对模块的配置项,使用者可以自定义配置
写个starter
开发步骤
- 创建maven工程并在pom文件添加所需要的依赖
- 创建配置类,定义配置项,指明配置前缀
- 创建自动装配类
- 在resources下面创建META-INF文件夹,在META-INF下面创建spring.factories,然后在这个文件里面定义需要自动装配的类
正式开始
我们就写个简单的线程池工厂来试试如何写一个starter
在pom文件添加所需要的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<!-- 这个插件要求项目必须要有main方法才能编译 -->
<!--<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>-->
创建配置类,定义配置项,指明配置前缀
定义一个创建线程池所需要的配置类
创建线程池需要那些配置项
- 核心线程数
- 最大线程数
- 存活时间
- 时间单位TimeUnit
- 阻塞队列
- 线程工厂
- 拒绝策略
我们将前三位参数定义到配置项(后面的都是对象,不好在配置文件配置;如果有好的方法可以配置的,可以交流一下),前缀名定义为:pool。
涉及到一个注解
- @ConfigurationProperties 指定配置类
看下代码
@ConfigurationProperties(prefix = ThreadPoolProperties.PREFIX)
public class ThreadPoolProperties {
public static final String PREFIX = "thread";
/**
* 线程工厂名
*/
private String factoryName;
/**
* 业务线程名
*/
private String businessName;
/**
* 线程池配置
*/
private PoolConfig poolConfig;
public String getFactoryName() {
return factoryName;
}
public void setFactoryName(String factoryName) {
this.factoryName = factoryName;
}
public String getBusinessName() {
return businessName;
}
public void setBusinessName(String businessName) {
this.businessName = businessName;
}
public PoolConfig getPoolConfig() {
return poolConfig;
}
public void setPoolConfig(PoolConfig poolConfig) {
this.poolConfig = poolConfig;
}
public static class PoolConfig{
/**
* 核心线程数
*/
private Integer corePoolSize;
/**
* 最大线程数
*/
private Integer maxPoolSize;
/**
* 超出核心线程数的线程存活时间
*/
private Long keepAliveTime;
public Integer getCorePoolSize() {
return corePoolSize;
}
public void setCorePoolSize(Integer corePoolSize) {
this.corePoolSize = corePoolSize;
}
public Integer getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(Integer maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public Long getKeepAliveTime() {
return keepAliveTime;
}
public void setKeepAliveTime(Long keepAliveTime) {
this.keepAliveTime = keepAliveTime;
}
}
}
factoryName和businessName是为了给线程池的线程去个有区别度的名字,看下面的线程工厂就知道了。
public class DefaultThreadFactory implements ThreadFactory {
/**
* 线程名前缀
*/
private final StringBuilder namePrefix = new StringBuilder();
/**
* 线程数量计数器
*/
private final AtomicInteger nextId = new AtomicInteger(1);
/**
*
* @param factoryName 工厂名
* @param businessName 业务名
*/
public DefaultThreadFactory(String factoryName, String businessName) {
namePrefix.append("pool-").append(factoryName).append("-").append(businessName).append("-worker-");
}
@Override
public Thread newThread(Runnable r) {
return new Thread(null,r,namePrefix.toString() + nextId.getAndIncrement(),0);
}
}
创建自动装配类
线程池的配置已经做好了,接下来我们就要实例化一个线程池工厂了。需要添加两个注解:
- @Configuration 定义实例化配置类
- @EnableConfigurationProperties 自动配置属性
@Configuration
@EnableConfigurationProperties(ThreadPoolProperties.class)
public class ThreadPoolConfiguration {
@Bean
public ThreadPoolFactory threadPoolFactory(ThreadPoolProperties threadPoolProperties){
return new ThreadPoolFactory(threadPoolProperties);
}
}
往spring.factories添加需要自动装配的类
首先创建spring.factories文件,如图
然后就是添加自动装配的类了
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com/mumu/wen/threadPool/config/ThreadPoolConfiguration
最后我们编译一下这个maven项目,推送到maven仓库就可以引入使用了。
如何使用这个自定义starter
引入依赖
<dependency>
<groupId>com.mumu.wen</groupId>
<artifactId>thread-pool-springboot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
在application.yml配置属性
thread:
business-name: test
factory-name: test-factory
pool-config:
core-pool-size: 2
max-pool-size: 10
keep-alive-time: 100
项目中使用
@Autowired
private ThreadPoolFactory threadPoolFactory;
threadPoolFactory.newDefaultThreadPool().execute(() -> {
System.out.println("#######################自定义线程池starter已启动!" + Thread.currentThread().getName() + "########################");
});
结尾
starter是不是并没有想象的那么遥不可及,如果下次还有面试官问这个问题。直接把项目地址甩给他。哈哈哈。