跳到主要内容

SpringBoot自定义Starter开发

Starter的设计理念

什么是Starter

Starter是SpringBoot提供的一种依赖聚合机制,将某个功能所需的所有依赖、配置和自动装配逻辑打包成一个独立模块,让其他项目能够通过引入一个依赖快速集成该功能。

官方Starter示例

spring-boot-starter-data-redis包含:

  • Redis客户端(Lettuce/Jedis)
  • Spring Data Redis
  • 连接池配置
  • 序列化器配置
  • 自动配置类

开发者只需:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis:
host: localhost
port: 6379

自定义Starter的价值

统一技术栈:公司内部多个项目使用相同的技术组件时,封装成Starter可以:

  • 避免重复配置
  • 统一版本管理
  • 简化新项目接入
  • 便于技术升级

典型应用场景:

  • 分布式任务调度(XXL-Job、ElasticJob)
  • 链路追踪(SkyWalking、Zipkin)
  • 消息队列(RocketMQ、Kafka)
  • 对象存储(OSS、MinIO)
  • 短信服务、支付网关等

自定义Starter开发实战

项目结构

创建独立Maven项目:

xxl-job-spring-boot-starter/
├── pom.xml
└── src/
└── main/
├── java/
│ └── com/company/starter/xxljob/
│ ├── config/
│ │ └── XxlJobAutoConfiguration.java
│ └── properties/
│ └── XxlJobProperties.java
└── resources/
└── META-INF/
└── spring/
└── org.springframework.boot.autoconfigure.AutoConfiguration.imports

步骤一:定义配置属性类

使用@ConfigurationProperties绑定配置:

package com.company.starter.xxljob.properties;

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

/**
* XXL-Job配置属性
*/
@ConfigurationProperties(prefix = XxlJobProperties.PREFIX)
public class XxlJobProperties {

public static final String PREFIX = "spring.xxl.job";

/**
* 是否启用XXL-Job
*/
private boolean enabled = true;

/**
* 调度中心地址
*/
private String adminAddresses;

/**
* 访问令牌
*/
private String accessToken;

/**
* 执行器AppName
*/
private String appName;

/**
* 执行器IP(可选)
*/
private String ip;

/**
* 执行器端口(默认9999)
*/
private int port = 9999;

/**
* 日志存储路径
*/
private String logPath = "/data/applogs/xxl-job";

/**
* 日志保留天数(默认30天)
*/
private int logRetentionDays = 30;

// Getter和Setter方法
public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public String getAdminAddresses() {
return adminAddresses;
}

public void setAdminAddresses(String adminAddresses) {
this.adminAddresses = adminAddresses;
}

public String getAccessToken() {
return accessToken;
}

public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

public String getAppName() {
return appName;
}

public void setAppName(String appName) {
this.appName = appName;
}

public String getIp() {
return ip;
}

public void setIp(String ip) {
this.ip = ip;
}

public int getPort() {
return port;
}

public void setPort(int port) {
this.port = port;
}

public String getLogPath() {
return logPath;
}

public void setLogPath(String logPath) {
this.logPath = logPath;
}

public int getLogRetentionDays() {
return logRetentionDays;
}

public void setLogRetentionDays(int logRetentionDays) {
this.logRetentionDays = logRetentionDays;
}
}

配置映射关系:

步骤二:编写自动配置类

package com.company.starter.xxljob.config;

import com.company.starter.xxljob.properties.XxlJobProperties;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

/**
* XXL-Job自动配置类
*/
@AutoConfiguration // SpringBoot 2.7+推荐使用
@EnableConfigurationProperties(XxlJobProperties.class) // 启用配置属性
public class XxlJobAutoConfiguration {

private static final Logger logger = LoggerFactory.getLogger(XxlJobAutoConfiguration.class);

/**
* 创建XXL-Job执行器Bean
*/
@Bean
@ConditionalOnMissingBean // 容器中不存在时才创建
@ConditionalOnProperty(
prefix = XxlJobProperties.PREFIX,
name = "enabled",
havingValue = "true",
matchIfMissing = true // 未配置时默认启用
)
public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties properties) {
logger.info("初始化XXL-Job执行器, AppName: {}", properties.getAppName());

XxlJobSpringExecutor executor = new XxlJobSpringExecutor();

// 设置调度中心地址
executor.setAdminAddresses(properties.getAdminAddresses());

// 设置执行器信息
executor.setAppname(properties.getAppName());
executor.setIp(properties.getIp());
executor.setPort(properties.getPort());

// 设置访问令牌
executor.setAccessToken(properties.getAccessToken());

// 设置日志配置
executor.setLogPath(properties.getLogPath());
executor.setLogRetentionDays(properties.getLogRetentionDays());

return executor;
}
}

核心注解说明:

注解作用
@AutoConfiguration标识自动配置类(SpringBoot 2.7+)
@EnableConfigurationProperties启用配置属性类
@ConditionalOnMissingBean容器中不存在该Bean时才创建
@ConditionalOnProperty指定属性满足条件时才生效

步骤三:注册自动配置类

SpringBoot 2.7之前:使用spring.factories

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.company.starter.xxljob.config.XxlJobAutoConfiguration

SpringBoot 2.7及之后(推荐):使用AutoConfiguration.imports

# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.company.starter.xxljob.config.XxlJobAutoConfiguration

配置文件位置:

src/main/resources/
└── META-INF/
└── spring/
└── org.springframework.boot.autoconfigure.AutoConfiguration.imports

步骤四:配置项目依赖

pom.xml:

<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.company</groupId>
<artifactId>xxl-job-spring-boot-starter</artifactId>
<version>1.0.0</version>

<dependencies>
<!-- SpringBoot核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.0</version>
</dependency>

<!-- XXL-Job核心依赖 -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>

<!-- 配置处理器(生成配置元数据) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.7.0</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>

步骤五:打包发布

mvn clean install

发布到私服:

<distributionManagement>
<repository>
<id>company-releases</id>
<url>http://nexus.company.com/repository/maven-releases/</url>
</repository>
</distributionManagement>
mvn clean deploy

使用自定义Starter

引入依赖

<dependency>
<groupId>com.company</groupId>
<artifactId>xxl-job-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>

配置文件

spring:
xxl:
job:
enabled: true
admin-addresses: http://localhost:8080/xxl-job-admin
access-token: default_token
app-name: order-service
port: 9999
log-path: /data/logs/xxl-job
log-retention-days: 7

编写任务处理器

package com.company.order.job;

import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;

@Component
public class OrderJobHandler {

/**
* 订单超时取消任务
*/
@XxlJob("orderTimeoutCancelJob")
public void handleTimeoutOrder() {
System.out.println("执行订单超时取消任务...");
// 业务逻辑
}

/**
* 订单数据统计任务
*/
@XxlJob("orderStatisticsJob")
public void handleStatistics() {
System.out.println("执行订单统计任务...");
// 业务逻辑
}
}

启动应用

@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}

启动日志:

初始化XXL-Job执行器, AppName: order-service
XXL-Job执行器注册成功, 调度中心: http://localhost:8080/xxl-job-admin

高级特性

条件化配置

场景:开发环境禁用XXL-Job

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = XxlJobProperties.PREFIX,
name = "enabled",
havingValue = "true"
)
@Profile("!dev") // 非开发环境才生效
public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties properties) {
// ...
}

配置元数据

添加spring-boot-configuration-processor后,IDE会提供配置提示:

{
"properties": [
{
"name": "spring.xxl.job.admin-addresses",
"type": "java.lang.String",
"description": "XXL-Job调度中心地址,多个用逗号分隔",
"defaultValue": null
},
{
"name": "spring.xxl.job.enabled",
"type": "java.lang.Boolean",
"description": "是否启用XXL-Job",
"defaultValue": true
}
]
}

支持多环境配置

# application-dev.yml
spring:
xxl:
job:
enabled: false # 开发环境禁用

# application-prod.yml
spring:
xxl:
job:
enabled: true
admin-addresses: http://prod-xxl-job:8080/xxl-job-admin

提供默认值

@ConfigurationProperties(prefix = "spring.xxl.job")
public class XxlJobProperties {

private boolean enabled = true; // 默认启用

private int port = 9999; // 默认端口

private String logPath = System.getProperty("user.home") + "/logs/xxl-job"; // 默认路径
}

Starter开发最佳实践

命名规范

官方Starter:spring-boot-starter-{name}

第三方Starter:{name}-spring-boot-starter

示例:

  • mybatis-spring-boot-starter
  • druid-spring-boot-starter
  • spring-boot-starter-myproject(不推荐)

依赖管理

使用optional依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional> <!-- 标记为可选 -->
</dependency>

避免传递依赖冲突:

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>jconsole</artifactId>
</exclusion>
</exclusions>
</dependency>

提供禁用开关

@ConditionalOnProperty(
prefix = "spring.xxl.job",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 默认启用,允许用户配置false禁用
)

日志规范

private static final Logger logger = LoggerFactory.getLogger(XxlJobAutoConfiguration.class);

logger.info("初始化XXL-Job执行器, AppName: {}", properties.getAppName());
logger.debug("XXL-Job配置详情: {}", properties);

文档与示例

提供完整的README.md:

# XXL-Job SpringBoot Starter

## 快速开始

### 1. 添加依赖

```xml
<dependency>
<groupId>com.company</groupId>
<artifactId>xxl-job-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
```

### 2. 配置

```yaml
spring:
xxl:
job:
admin-addresses: http://localhost:8080/xxl-job-admin
app-name: demo-service
```

### 3. 编写任务

```java
@Component
public class DemoJobHandler {
@XxlJob("demoJob")
public void execute() {
// 业务逻辑
}
}
```

## 配置说明

| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| spring.xxl.job.enabled | 是否启用 | true |
| spring.xxl.job.admin-addresses | 调度中心地址 ||

总结

自定义Starter开发的核心步骤:

通过封装Starter,可以极大简化技术组件的集成工作,提升团队开发效率。