在Spring Boot项目里,不同业务模块对ID生成的需求往往存在差异,比如核心业务表需要有序且高性能的雪花ID,辅助表可以使用简单的UUID,历史归档表可能需要兼容旧系统的自增规则。基于继承的条件化ID生成策略可以通过抽象父类和具体实现类拆分逻辑,再结合Spring的条件装配能力,实现不同场景下自动匹配对应的ID生成器。

核心抽象父类定义
首先定义所有ID生成器需要遵循的抽象父类,统一生成方法的签名,后续不同的生成策略都继承这个父类实现具体逻辑。
// 抽象ID生成器父类
public abstract class AbstractIdGenerator {
/**
* 生成ID的抽象方法,由子类实现具体逻辑
* @return 生成的ID字符串
*/
public abstract String generateId();
/**
* 判断当前生成器是否支持指定的实体类型
* @param entityClass 实体类Class对象
* @return 是否支持
*/
public abstract boolean supports(Class<?> entityClass);
}
具体ID生成策略实现
接下来实现三种常见的ID生成策略,分别适配不同的业务场景,每个实现类都继承AbstractIdGenerator抽象类。
雪花算法ID生成器
适用于需要有序、高性能、分布式唯一ID的核心业务表,比如用户、订单等实体。
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
// 当配置文件中id.generator.type=snowflake时加载该生成器
@Component
@ConditionalOnProperty(name = "id.generator.type", havingValue = "snowflake")
public class SnowflakeIdGenerator extends AbstractIdGenerator {
// 雪花算法核心参数,实际项目中可配置化
private final long workerId = 1L;
private final long datacenterId = 1L;
private long sequence = 0L;
private final long twepoch = 1288834974657L;
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final long sequenceBits = 12L;
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private long lastTimestamp = -1L;
@Override
public String generateId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException("时钟回拨,无法生成ID");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
long id = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
return String.valueOf(id);
}
@Override
public boolean supports(Class<?> entityClass) {
// 支持标记了SnowflakeId注解的实体
return entityClass.getAnnotation(SnowflakeId.class) != null;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
}
UUID生成器
适用于对ID有序性无要求、不需要依赖外部组件的辅助表,比如操作日志、临时数据等实体。
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import java.util.UUID;
// 当配置文件中id.generator.type=uuid时加载该生成器
@Component
@ConditionalOnProperty(name = "id.generator.type", havingValue = "uuid")
public class UuidIdGenerator extends AbstractIdGenerator {
@Override
public String generateId() {
return UUID.randomUUID().toString().replace("-", "");
}
@Override
public boolean supports(Class<?> entityClass) {
// 支持标记了UuidId注解的实体
return entityClass.getAnnotation(UuidId.class) != null;
}
}
数据库自增ID生成器
适用于兼容旧系统、依赖数据库自增能力的实体,比如历史归档表等。
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
// 当配置文件中id.generator.type=auto_increment时加载该生成器
@Component
@ConditionalOnProperty(name = "id.generator.type", havingValue = "auto_increment")
public class AutoIncrementIdGenerator extends AbstractIdGenerator {
@Autowired
private DataSource dataSource;
@Override
public String generateId() {
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT LAST_INSERT_ID()");
ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return String.valueOf(rs.getLong(1));
}
throw new RuntimeException("获取自增ID失败");
} catch (Exception e) {
throw new RuntimeException("获取自增ID异常", e);
}
}
@Override
public boolean supports(Class<?> entityClass) {
// 支持标记了AutoIncrementId注解的实体
return entityClass.getAnnotation(AutoIncrementId.class) != null;
}
}
条件注解与实体标记
为了区分不同实体对应的ID生成策略,我们定义对应的注解,实体类上标记对应注解即可关联生成器。
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SnowflakeId {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UuidId {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoIncrementId {
}
ID生成器管理类
定义一个管理类,自动注入所有AbstractIdGenerator的实现类,根据实体类型匹配对应的生成器。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class IdGeneratorManager {
@Autowired
private List<AbstractIdGenerator> idGenerators;
/**
* 根据实体类获取对应的ID生成器并生成ID
* @param entityClass 实体类Class对象
* @return 生成的ID
*/
public String generateId(Class<?> entityClass) {
for (AbstractIdGenerator generator : idGenerators) {
if (generator.supports(entityClass)) {
return generator.generateId();
}
}
throw new RuntimeException("未找到对应实体" + entityClass.getName() + "的ID生成器");
}
}
实际使用示例
首先在配置文件中指定当前启用的ID生成器类型,比如启用雪花算法:
id.generator.type=snowflake
然后定义对应的实体类,标记对应的注解:
// 用户实体使用雪花算法生成ID
@SnowflakeId
public class User {
private String id;
private String username;
private String password;
// 省略getter、setter
}
// 操作日志实体使用UUID生成ID
@UuidId
public class OperationLog {
private String id;
private String userId;
private String content;
// 省略getter、setter
}
在业务代码中注入IdGeneratorManager即可生成对应实体的ID:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private IdGeneratorManager idGeneratorManager;
@PostMapping("/user")
public String createUser() {
User user = new User();
// 生成用户ID
String userId = idGeneratorManager.generateId(User.class);
user.setId(userId);
user.setUsername("testUser");
// 后续保存逻辑
return userId;
}
}
方案优势总结
- 复用性强:公共的判断逻辑可以放在抽象父类中,避免重复代码
- 扩展性好:新增ID生成策略只需要新增继承抽象父类的实现类,无需修改原有代码
- 适配灵活:通过条件注解和实体注解可以灵活匹配不同场景的ID生成需求,切换成本低
- 符合开闭原则:对扩展开放,对修改关闭,后续迭代维护更方便
Spring_Boot条件化ID生成继承策略ID生成器策略模式修改时间:2026-07-11 02:09:41