前言

前面写过一个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包供外部工程使用,我还是习惯叫配置化注入。

Springboot学习笔记(六)-配置化注入的更多相关文章

  1. SpringBoot学习笔记(1):配置Mybatis

    SpringBoot学习笔记(1):配置Mybatis 反思:如果自己写的笔记自己都看不懂,那就不要拿出来丢人现眼! IDEA插件 Free MyBatis Plugin插件可以让我们的MyBatis ...

  2. SpringBoot学习笔记(7):Druid使用心得

    SpringBoot学习笔记(7):Druid使用心得 快速开始 添加依赖 <dependency> <groupId>com.alibaba</groupId> ...

  3. SpringBoot学习笔记(8):事物处理

    SpringBoot学习笔记(8):事物处理 快速入门 在传统的JDBC事务代码开发过程中,业务代码只有一部分,大部分都是与JDBC有关的功能代码,比如数据库的获取与关闭以及事务的提交与回滚.大量的t ...

  4. springboot学习笔记:9.springboot+mybatis+通用mapper+多数据源

    本文承接上一篇文章:springboot学习笔记:8. springboot+druid+mysql+mybatis+通用mapper+pagehelper+mybatis-generator+fre ...

  5. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  6. java学习笔记12--国际化

    java学习笔记12--国际化 国际化的操作就是指一个程序可以同时适应多门语言,即:如果现在程序者是中国人,则会以中文为显示文字,如果现在程序的使用者是英国人,则会以英语为显示的文字,也就是说可以通过 ...

  7. SpringBoot学习笔记

    SpringBoot个人感觉比SpringMVC还要好用的一个框架,很多注解配置可以非常灵活的在代码中运用起来: springBoot学习笔记: .一.aop: 新建一个类HttpAspect,类上添 ...

  8. SpringBoot学习笔记(14):使用SpringBootAdmin管理监控你的应用

    SpringBoot学习笔记(14):使用SpringBootAdmin管理监控你的应用 Spring Boot Admin是一个管理和监控Spring Boot应用程序的应用程序.本文参考文档: 官 ...

  9. SpringBoot学习笔记(3):静态资源处理

    SpringBoot学习笔记(3):静态资源处理 在web开发中,静态资源的访问是必不可少的,如:Html.图片.js.css 等资源的访问. Spring Boot 对静态资源访问提供了很好的支持, ...

随机推荐

  1. PHP算式验证码和汉字验证码的实现方法

    在PHP网站开发中,验证码可以有效地保护我们的表单不被恶意提交,但是如果不使用算式验证码或者汉字验证码,仅仅使用简单的字母或者数字验证码,这样的验证码方案真的安全吗? 大家知道简单数字或者字母验证码很 ...

  2. js签名

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  3. 多线程里面this.getName()和currentThread.getName()有什么区别

    public class hello extends Thread { public hello(){ System.out.println("Thread.currentThread(). ...

  4. zabbix 创建监控项

    项目是在Zabbix收集数据的基础 ,所有项目都是围绕主机,找到创建的主机 点击 Configuration > hosts > ltems 点击 Create item Name:输入C ...

  5. centos7 重置root 密码

    重置Centos 7 Root密码的方式和Centos 6完全不同.让我来展示一下到底如何操作. 1 - 在启动grub菜单,选择编辑选项启动 2 - 按键盘e键,来进入编辑界面 3 - 找到Linu ...

  6. C#高级编程9 第18章 部署

    C#高级编程9 第18章 部署 使用 XCopy 进行部署 本主题演示如何通过将应用程序文件从一台计算机复制到另一台计算机来部署应用程序. 1.将项目中生成的程序集复制到目标计算机,生成的程序集位于项 ...

  7. C++泛型编程(2)--通过排序和查找元素理解迭代器

    许多C++开源库(stl,opencv,ros和blas等)都使用了大量的泛型编程的思想,如果不理解这些思想,将很难看懂代码,而<泛型编程与STL>一书对理解泛型编程思想非常的有帮助,这里 ...

  8. 机器学习笔记(2):线性回归-使用gluon

    代码来自:https://zh.gluon.ai/chapter_supervised-learning/linear-regression-gluon.html from mxnet import ...

  9. Standard Series Values in a Decade for Resistances and Capacitances E24 E48 E96

    E3     50% tolerance (no longer used)E6     20% tolerance (now seldom used)E12   10% toleranceE24    ...

  10. 关于RabbitMQ关键性问题的总结

    摘要:本篇是本人对RabbitMQ使用的关键性问题进行的总结,如性能上限.数据存储.集群等, 具体的RabbitMQ概念.安装.使用方法.SpringAMQP配置,假设读者已有了基础. 1.      ...