如何封装独立 SpringBoot Starter
如何封装独立 SpringBoot Starter
前言
前面我们实现了限流 + 幂等 + Sentinel+Nacos 整套防护能力,如果每个微服务都复制切面、注解、工具类、配置,会出现大量重复代码,维护极其麻烦。
SpringBoot Starter 核心作用:把通用组件抽离成独立 jar 包,业务项目仅引入一行依赖即可自动装配所有功能,零配置侵入。
本文手把手完整教学:从零封装自定义 starter,分「命名规范、工程分层、自动装配、配置绑定、业务接入、踩坑总结」全流程,以上文限流幂等安全框架为实战案例。
一、Starter 两种分类 & 命名规范
SpringBoot 官方约定两种 starter,规范必须遵守,否则辨识度低:
-
官方 Starter
命名格式:
spring-boot-starter-xxx例:spring-boot-starter-web、spring-boot-starter-data-redis
-
自定义业务 / 第三方 Starter(我们用这种)
命名格式:
xxx-spring-boot-starter例:security-spring-boot-starter、mybatis-plus-spring-boot-starter
模块拆分标准(二分法,标准企业结构)
成熟项目建议拆两个模块,职责分离:
-
xxx-spring-boot-autoconfigure
:自动装配核心模块
存放配置类、切面、工具、注解、属性绑定,所有业务逻辑代码
-
xxx-spring-boot-starter
:空壳依赖聚合模块
不写任何 Java 代码,仅 pom 引入 autoconfigure,方便业务项目引入依赖
简易方案(个人小项目):合并为单个 starter 模块,autoconfigure 代码直接放 starter 内,适合简单组件。本文演示简易单模块方案,上手更快。
二、整体工程目录结构(安全防护 starter 示例)
security-spring-boot-starter
├── pom.xml # starter聚合依赖
└── src
└── main
├── java/com/security/starter
│ ├── anno # 自定义注解 @Idempotent
│ ├── aop # 幂等切面 IdempotentAspect
│ ├── config # 自动装配配置类
│ │ ├── SecurityAutoConfiguration.java # 总装配入口
│ │ └── SentinelNacosAutoConfig.java # Sentinel nacos持久化配置
│ ├── core # 工具类:IdempotentUtil、Result统一返回
│ ├── prop # 配置属性绑定类 SecurityProperties
│ └── exception # 全局统一异常处理器
└── resources
└── META-INF
└── spring.factories # SpringBoot自动装配核心文件
三、分步完整编码实现
3.1 父工程版本统一(可选,多模块管理)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.security</groupId>
<artifactId>security-parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<spring.boot.version>2.7.15</spring.boot.version>
<spring.cloud.alibaba.version>2022.0.0.0</spring.cloud.alibaba.version>
<sentinel.version>1.8.6</sentinel.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- SpringBoot 父依赖统一管理 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 统一版本 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
3.2 starter 模块 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<parent>
<groupId>com.security</groupId>
<artifactId>security-parent</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>security-spring-boot-starter</artifactId>
<version>1.0.0</version>
<name>限流幂等安全框架starter</name>
<dependencies>
<!-- Spring Web 基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- AOP切面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Nacos配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- Sentinel核心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel Nacos持久化数据源 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>${sentinel.version}</version>
</dependency>
<!-- fastjson序列化解析sentinel规则 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.32</version>
</dependency>
<!-- 配置元数据,yml自动提示 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.3 配置属性绑定类 SecurityProperties
作用:业务项目 yml 中自定义配置,绑定到实体,控制开关、前缀、超时时间等参数
package com.security.starter.prop;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 配置绑定前缀:security.framework
*/
@ConfigurationProperties(prefix = "security.framework")
public class SecurityProperties {
// 是否开启整套防护框架,默认开启
private boolean enable = true;
// 幂等token redis key前缀
private String idempotentPrefix = "idempotent:token:";
// Nacos存储sentinel规则分组
private String nacosGroup = "SENTINEL_GROUP";
// nacos dataId前缀
private String dataIdPrefix = "sentinel-rule-";
// getter & setter
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getIdempotentPrefix() {
return idempotentPrefix;
}
public void setIdempotentPrefix(String idempotentPrefix) {
this.idempotentPrefix = idempotentPrefix;
}
public String getNacosGroup() {
return nacosGroup;
}
public void setNacosGroup(String nacosGroup) {
this.nacosGroup = nacosGroup;
}
public String getDataIdPrefix() {
return dataIdPrefix;
}
public void setDataIdPrefix(String dataIdPrefix) {
this.dataIdPrefix = dataIdPrefix;
}
}
3.4 自动装配总入口 SecurityAutoConfiguration
核心:条件注解控制组件是否注入,导入子配置类,注册 Bean
package com.security.starter.config;
import com.security.starter.aop.IdempotentAspect;
import com.security.starter.core.IdempotentUtil;
import com.security.starter.prop.SecurityProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* starter自动装配主类
*/
@Configuration
// 开启配置属性绑定
@EnableConfigurationProperties(SecurityProperties.class)
// 条件:配置security.framework.enable=true才加载,不配置默认true
@ConditionalOnProperty(
prefix = "security.framework",
name = "enable",
havingValue = "true",
matchIfMissing = true
)
// 导入sentinel nacos子配置
@Import(SentinelNacosAutoConfig.class)
public class SecurityAutoConfiguration {
/** 注入幂等工具类 */
@Bean
public IdempotentUtil idempotentUtil() {
return new IdempotentUtil();
}
/** 注入幂等AOP切面 */
@Bean
public IdempotentAspect idempotentAspect() {
return new IdempotentAspect();
}
}
3.5 子配置:Sentinel Nacos 规则持久化配置
package com.security.starter.config;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.security.starter.prop.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
@Configuration
public class SentinelNacosAutoConfig {
@Resource
private NacosConfigManager nacosConfigManager;
@Resource
private SecurityProperties securityProperties;
@PostConstruct
public void loadFlowRule() {
String appName = System.getProperty("spring.application.name");
String dataId = securityProperties.getDataIdPrefix() + appName;
String group = securityProperties.getNacosGroup();
// 构建nacos数据源,监听流控规则变化
ReadableDataSource<String, List<FlowRule>> flowDataSource = new NacosDataSource<>(
nacosConfigManager.getNacosConfigService(),
group,
dataId,
source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {})
);
// 注册规则管理器,动态监听更新
FlowRuleManager.register2Property(flowDataSource.getProperty());
}
}
3.6 核心业务代码(注解、切面、工具、返回体直接放入 starter)
anno/Idempotent.java幂等注解aop/IdempotentAspect.java幂等校验切面core/IdempotentUtil.javaRedis Lua 原子工具类core/Result.java全局统一返回体exception/GlobalExceptionHandler.java全局异常处理器
3.7 关键文件 spring.factories(自动装配核心)
路径:resources/META-INF/spring.factories
作用:SpringBoot 项目启动时,SPI 机制自动读取该文件,加载我们的自动装配类,不需要业务项目加任何 @Enable 注解
factories
# 自动装配配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.security.starter.config.SecurityAutoConfiguration
3.8 可选:配置元数据(yml 提示)
resources/META-INF 新建 spring-configuration-metadata.json,idea 写 yml 时自动提示配置项,优化开发体验,非必需。
四、打包本地安装 & 推送到私服
4.1 本地 Maven 打包安装(本地测试)
在 starter 根目录执行 maven 命令:
mvn clean install -Dmaven.test.skip=true
执行完成后,jar 包存入本地 maven 仓库,业务项目可直接依赖。
4.2 推送私有 Nexus 私服(多团队共享)
pom 增加 distributionManagement 私服地址,执行 mvn deploy 推送,所有微服务统一拉取。
五、业务微服务如何接入 starter
5.1 引入一行依赖
<dependency>
<groupId>com.security</groupId>
<artifactId>security-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
5.2 application.yml 最简配置
spring:
application:
name: order-service
redis:
host: 127.0.0.1
port: 6379
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: 127.0.0.1:8080
# 自定义starter配置(全部有默认值,可省略)
security:
framework:
enable: true
nacos-group: SENTINEL_GROUP
5.3 Controller 直接使用,无需任何额外配置
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Resource
private IdempotentUtil idempotentUtil;
@GetMapping("/getToken")
public Result<String> getToken(){
return Result.success(idempotentUtil.generateToken(600));
}
@PostMapping("/submit")
@SentinelResource(value = "submitOrder", blockHandler = "blockHandler")
@Idempotent(message = "请勿重复提交订单")
public Result<String> submitOrder(){
return Result.success("下单成功");
}
public Result<String> blockHandler(BlockException e){
return Result.fail("访问过于频繁,请稍后重试");
}
}
六、核心注解详解(starter 条件装配关键)
-
@Configuration标记当前类为配置类,Spring 启动扫描注册 Bean
-
@EnableConfigurationProperties开启配置绑定,将 yml 配置注入 Properties 实体
-
@ConditionalOnProperty根据 yml 配置开关控制整套组件是否生效
-
@ConditionalOnClass判断 class 存在才注入 Bean,例如存在 RedisTemplate 才装配 Redis 工具
-
@ConditionalOnMissingBean业务项目自定义 Bean 时,覆盖 starter 默认 Bean,提供扩展能力
-
@Import导入其他配置类,拆分复杂配置,解耦代码
七、企业级扩展优化方案
-
支持用户自定义覆盖 Bean
工具类、切面使用
@ConditionalOnMissingBean,业务项目可自定义实现替换 starter 默认逻辑。
-
多环境配置隔离
Properties 增加环境标识,Nacos 分组区分 dev/test/prod 规则。
-
扩展 starter 自动提示
配置 spring-configuration-processor 依赖,自动生成配置提示文件。
-
拆分多规则持久化
在 Sentinel 配置中扩展熔断、热点参数、系统规则 Nacos 数据源。
-
增加日志埋点
AOP 切面记录限流、重复提交拦截日志,便于线上排查。
-
适配 Gateway 网关
区分 web 环境和 reactive 响应式 web,增加
@ConditionalOnWebApplication适配网关。
八、常见踩坑问题总结
1. starter 装配不生效,切面 / 工具类未注入
- 检查
resources/META-INF/spring.factories文件路径、类全限定名是否写错; - maven 打包时是否跳过资源文件,build 节点配置 resource 拷贝;
- 确认配置开关
security.framework.enable=true。
2. yml 配置不生效,属性无法注入
- 缺少
@EnableConfigurationProperties注解; - 配置前缀与 Properties 类注解不一致;
- 未引入 configuration-processor 依赖,idea 无提示不影响运行。
3. Nacos Sentinel 规则拉取不到
- nacos dataId、group 与配置类完全匹配;
- 缺少 sentinel-datasource-nacos 依赖;
- 服务必须配置 spring.application.name。
4. AOP 切面执行顺序错乱
@SentinelResource 是拦截器,优先级高于 SpringAOP,天然先限流后幂等,无需额外调整。
5. 打包后本地项目无法引用
执行 install 命令,跳过测试;groupId、artifactId 和依赖引入保持一致。
九、总结
- SpringBoot Starter 核心原理:SPI 机制 + 条件注解自动装配,实现组件开箱即用;
- 标准封装流程:创建模块→编写业务组件→属性绑定配置类→编写自动装配入口→配置 spring.factories→打包;
- 优势:消除多项目重复代码、统一技术规范、业务项目极低接入成本、统一升级维护;
- 本文案例可直接复用,基于前面限流幂等 Sentinel 全套代码,一键封装成企业通用安全防护 Starter。
更多推荐


所有评论(0)