「这是我参与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机制导入自动配置类
- 在classpath下创建META-INF文件夹,在META-INF文件夹下创建一个名为spring.factories文件.
- 将我们的自动配置类以键值对的形式配置到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!
三:简单测试
创建一个项目简单测试一下:
- 引入我们自定义的starter
<dependency>
<groupId>com.luoy</groupId>
<artifactId>xxl-job-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
- 通过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的容器中,已经完成了自动装配
并且在properties中也可以配置我们需要定义的xxl-job相关属性。
四:总结
本文通过自定义一个xxl-job为例,讲述如何自定义一个spring-boot的starer,如果大家理解了spring-boot自动装配的原理,那么自定义一个starter是非常简单的一件事。(看完本篇文章是不是有一种迫不及待的想加班为公司定义starter的冲动。)
注:在我的另一篇文章中已经很详细的讲解了Springboot如何实现自动装配,有兴趣的同学可以看下,文章地址:SpringBoot是如何实现自动装配的。
最后附上自定义xxl-job-starter的源码地址:gitee.com/yidaishi/xx…
如果有任何疑问或者不足,欢迎在下方留言。如果本文对你有所帮助,那么点个赞再走吧。