• Springboot学习笔记(六)-配置化注入


    前言

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

  • 相关阅读:
    fedora如何删除某个包且不删除依赖它的相关包
    git分支切换时的时间戳问题
    [Centos] ERROR: Could not find useradd in chroot, maybe the install failed?
    linux通过python设置系统默认编码
    linux设置系统时间和时区
    python: "TypeError: 'type' object is not subscriptable"
    如何搭建http服务仓库
    [转载]RPM中SPEC常用路径以及宏变量
    spec文件写作规范
    GeoServer中利用SLD配图之矢量图层配图
  • 原文地址:https://www.cnblogs.com/yw0219/p/9069714.html
Copyright © 2020-2023  润新知