前言

前面写过一个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. 响应式 Web 设计指南「基础篇」

    Web 是普遍存在的,也是无处不在的,Web可以适应任何尺寸的屏幕以及任何使用环境,因为Web有其固有的灵活性和可塑性. Web 再也不是某一平台独有的矿藏,而是真正成为了一张名副其实的大网,并将各种 ...

  2. data warehouse 1.0 vs 2.0

    data warehouse 1.01. EDW goal, separate data marts reqlity2. batch oriented etl3. IT driven BI - das ...

  3. __getattr__和__setattt__使用

    # coding:utf-8 """ __setattr__(self, name, value),如果要给name赋值,调用此方法 __getattr__(self, ...

  4. winform 中 给DataGridView的表头添加CheckBox

    在C/S架构中,给DataGridView的表头添加CheckBox控件: 添加类:   /// <summary>       /// 给DataGridView添加全选       / ...

  5. 几款流行的HTML5 UI 框架比较

    手机HTML5开发,大部分都使用现有的框架,这里简单比较几个流行的UI 框架.作者(启明星工作室 http://www.dotnetcms.org) 比较一下几款流行的HTML5框架,个人意见,仅供参 ...

  6. Android GUI之Activity、Window、View

    相信大家在接触Android之初就已经知道了Activity中的setContentView方法的作用了,很明显此方法是用于为Activity填充相应的布局的.那么,Activity是如何将填充的布局 ...

  7. PHP7通过yum源安装及性能测试

    提到PHP,肯定会有人说这是世界上最好的编程语言.单说流行程度,目前全球超过81.7%的服务器后端都采用了PHP语言,它驱动着全球超过2亿多个网站.上月初PHP7正式版发布,迎来自2004年以来最大的 ...

  8. 树莓派(RespberryPi)安装手记

    购买了两台树莓派,显示器接口是HDMI的,所以需要HDMI高清线连接到显示器,再加上SD卡做硬盘以及无线USB-WIFI,就可以玩一玩树莓派这个小东西了.以下是安装手记. 首先是制作“启动光盘”,其实 ...

  9. 最佳实战Docker持续集成图文详解

    最佳实战Docker持续集成图文详解 这是一种真正的容器级的实现,这个带来的好处,不仅仅是效率的提升,更是一种变革:开发人员第一次真正为自己的代码负责——终于可以跳过运维和测试部门,自主维护运行环境( ...

  10. 多线程本地图片载入演示样例【OpenCV】【Pthread】

    Pthread barrier的简单使用演示样例: C++代码例如以下: // ThreadingLoadImages.cpp : 定义控制台应用程序的入口点. // #include "s ...