如何自定义一个Springboot的starter--以定义一个XXL-job的starter为例

639 阅读4分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

一:简述

开发过程中,经常会有一些独立于业务之外的组件模块,如果我们将这些可独立于业务代码之外的功能模块封装成一个个starter,由SpringBoot为我们完成自动装配。然后在需要使用的时候再引用相关依赖,这样不仅可以简化我们的开发而且可以提高代码的复用。今天我们以定义一个xxl-job的starter为例,说明如何自定义一个属于自己的starter。

二:定义一个Springboot的Starter

我们以定义一个xxl-job的starter为例子。本文使用的xxl-job的版本是2.3.0

step1:创建一个maven工程,引入相关依赖

springboot约定自定义的第三方starter名称应该是xxx-spring-boot-starter,官方自己的starter名称是spring-boot-starter-xxx。既然springboot作为一个约定大于配置的框架,我们应该尽量遵守它的约定。所以我们创建一个项目的名称为xxl-job-spring-boot-starter的maven项目。并且引入自动装配以及xxl-job所需的相关依赖。

pom文件:

这里为了方便还引入了lombok的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.luoy</groupId>
    <artifactId>xxl-job-spring-boot-starter</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>xxl-job-spring-boot-starter</name>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <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>

        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

注:pom文件打包的插件不要使用springboot的插件,那样会把我们的starer打包成一个可运行的jar包,但是其他项目是不能依赖的,所以我们用一个简单的maven打包插件就行了。

step2:定义properties类

创建一个XxlJobProperties的类,并且通过@ConfigurationProperties注解来读取properties文件的配置。

package com.xxljobstarter.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author 20136
 */
@ConfigurationProperties(prefix = XxlJobProperties.PREFIX)
@Data
public class XxlJobProperties {

    static final String PREFIX = "xxl.job";

    /**
     * xxl-job-admin 地址
     */
    private String adminAddress;
    /**
     * access token
     */
    private String accessToken;

    private Executor executor = new Executor();


    @Data
    public static class Executor{

        /**
         * 执行器的name
         */
        private String appName;
        /**
         * 执行器ip
         */
        private String ip;
        /**
         * 执行器端口号 默认9999
         */
        private int port = 9999;
        /**
         * 日志存储路径
         */
        private String logPath = "/data/applogs/xxl-job/jobhandler";

        /**
         * 日志存储时间 默认30天
         */
        private int logretentiondays = 30;
    }
}

step3:定义自动配置类以及需要导入的bean

创建一个自动配置的类,在这里我们可以根据自己的条件利用@Conditional注解按条件导入bean。这里我们将xxl-job需要的XxlJobSpringExecutor加入到Spring的容器中,通过XxlJobProperties获取XxlJobSpringExecutor需要的属性。

注:XxlJobProperties我们通过@EnableConfigurationProperties注解导入到了Spring IoC容器中,这是因为后续我们会将XxlJobAutoConfiguration通过SPI的机制导入到Spring容器中,所以@EnableConfigurationProperties和@Bean能生效。

package com.xxljobstarter.autoconfiguration;


import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import com.xxljobstarter.properties.XxlJobProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@EnableConfigurationProperties(XxlJobProperties.class)
@Slf4j
public class XxlJobAutoConfiguration {

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties xxlJobProperties){

        log.info(">>>>>>>>>>> xxl-job config init.");

        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();

        xxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());

        xxlJobSpringExecutor.setAdminAddresses(xxlJobProperties.getAdminAddress());

        XxlJobProperties.Executor executor = xxlJobProperties.getExecutor();

        xxlJobSpringExecutor.setAppname(executor.getAppName());

        xxlJobSpringExecutor.setIp(executor.getAppName());

        xxlJobSpringExecutor.setPort(executor.getPort());

        xxlJobSpringExecutor.setLogPath(executor.getLogPath());

        xxlJobSpringExecutor.setLogRetentionDays(executor.getLogretentiondays());

        return xxlJobSpringExecutor;
    }
}

step4:利用Spring的SPI机制导入自动配置类

  1. 在classpath下创建META-INF文件夹,在META-INF文件夹下创建一个名为spring.factories文件.

20210321115809606.png

  1. 将我们的自动配置类以键值对的形式配置到spring.factories文件中,键为org.springframework.boot.autoconfigure.EnableAutoConfiguration,值就是我们自动配置类的全类名.
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.xxljobstarter.autoconfiguration.XxlJobAutoConfiguration

step5:利用maven进行打包

利用maven将我们自定义的starter install到本地或者是配置私服deploy到自己的私服(这里我就先install到自己本地),到这里我们自定义的starter也就完成了。

注:再次提醒,不要打包成可运行的jar!

三:简单测试

创建一个项目简单测试一下:

  1. 引入我们自定义的starter
        <dependency>
            <groupId>com.luoy</groupId>
            <artifactId>xxl-job-spring-boot-starter</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
  1. 通过ApplicationContext获取XxlJobSpringExecutor的bean,看其是否加入到Spring容器中。
package com.example;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import com.xxljobstarter.properties.XxlJobProperties;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@MapperScan(basePackages = "com.example")
public class ExampleApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(ExampleApplication.class, args);

        XxlJobSpringExecutor bean = run.getBean(XxlJobSpringExecutor.class);

        System.out.println(bean);
    }

}

通过控制台我们直到XxlJobSpringExecutor已经加入到Spring的容器中,已经完成了自动装配

1644502704(1).png

并且在properties中也可以配置我们需要定义的xxl-job相关属性。

1644502828(1).png

四:总结

本文通过自定义一个xxl-job为例,讲述如何自定义一个spring-boot的starer,如果大家理解了spring-boot自动装配的原理,那么自定义一个starter是非常简单的一件事。(看完本篇文章是不是有一种迫不及待的想加班为公司定义starter的冲动。)

注:在我的另一篇文章中已经很详细的讲解了Springboot如何实现自动装配,有兴趣的同学可以看下,文章地址:SpringBoot是如何实现自动装配的

最后附上自定义xxl-job-starter的源码地址:gitee.com/yidaishi/xx…

如果有任何疑问或者不足,欢迎在下方留言。如果本文对你有所帮助,那么点个赞再走吧。