欢迎阅读我的文章!更多精彩内容,欢迎关注:
• B站主页
小枫Geek
• 微信公众号Procode  


        在很多 Spring Boot 项目中,经常会出现一种很典型的现象:util 包越来越大,StringUtils、DateUtils、UserUtils、OrderUtils、CommonUtils……工具类越写越多,最终项目里充斥着大量 static 方法

        一开始大家写工具类是为了“方便复用”,但时间一长就会发现—— 代码虽然能跑,但项目结构却越来越混乱,逻辑难以维护。

        工具类本来是为了提升效率,但如果不    加控制,就会变成一种 架构层面的技术债务。今天我们就系统聊一聊:Spring Boot 项目为什么容易工具类泛滥?又该如何优雅避免?

1、为什么容易出现工具类泛滥

工具类泛滥并不是 Spring Boot 的问题,而是 开发习惯 + 架构设计问题

常见原因主要有四个。

1. 开发者习惯把“通用逻辑”丢进 Util

很多人遇到可复用代码时,第一反应是:

新建一个 Util

比如:

DateUtil.format()UserUtil.getCurrentUser()OrderUtil.calculatePrice()

这样写短期看起来很方便,但实际上隐藏了问题:

  • 业务逻辑被“工具化”

  • 代码语义变得模糊

  • 类的职责不清晰

例如:

OrderUtil.calculateDiscount()

这个逻辑其实属于 订单领域逻辑,而不是工具类。

2. 静态方法导致无法管理依赖

工具类一般都是:

public class XxxUtil {    public static void doSomething(){    }}

问题在于:static 方法无法被 Spring 管理。

这就带来几个问题:

  • 1.无法注入 Bean 

  • 2.不方便做 AOP 

  • 3.不方便测试 Mock

例如:

UserUtil.getCurrentUser()

如果后续用户来源变成 网关解析 / Token 解析 / Redis 缓存, 工具类就很难扩展。

3. 逻辑聚合越来越混乱

随着项目发展,工具类往往变成这样:

StringUtilDateUtilCollectionUtilCommonUtilBusinessUtil

其中最危险的是:

CommonUtil

这是一个“万物归一类”。

项目后期你会发现:这个类已经有 2000 行代码。

4. 工具类破坏面向对象设计

工具类的本质是:面向过程编程。

而 Java 和 Spring Boot 的设计哲学是:面向对象 + 依赖注入。

当项目大量使用工具类时,会出现:

  • 业务逻辑散落

  • 类之间关系断裂

  • 难以扩展

从架构角度来看,这是 代码结构退化

2、哪些代码才适合放工具类

并不是说 工具类完全不能用

关键是:工具类只应该放“无状态通用逻辑”。

典型例子包括:

1. 字符串处理

例如:

StringUtils.isBlank()StringUtils.camelToUnderline()

这种逻辑:

  • 无状态

  • 无业务含义

  • 高度复用

适合工具类。

2.日期时间处理

例如:

DateUtils.format()DateUtils.parse()

因为 Java 原生日期 API 比较复杂, 封装工具类可以简化使用。

3.加密与编码

例如:

MD5Util.encrypt()Base64Util.encode()

这些属于 纯算法逻辑

4.文件操作

例如:

FileUtil.readFile()FileUtil.writeFile()

也属于底层能力。

总结一句话:工具类只负责“技术能力”,不负责“业务逻辑”。

3、业务逻辑不要放工具类

一个非常重要的原则:业务逻辑必须属于业务对象。

例如:

错误写法:

OrderUtil.calculatePrice(order)

正确写法:

orderService.calculatePrice(order)

或者:

order.calculatePrice()

业务逻辑应该放在:

  • Service

  • Domain

  • Strategy

而不是 Util。

4、Spring Bean 替代工具类

如果某段逻辑:

  • 需要依赖其他组件

  • 需要扩展

  • 可能会改变

那就不要写工具类。直接写 Spring Bean。

例如:

错误写法:

UserUtil.getCurrentUser()

推荐写法:

@Componentpublic class UserContext {    public User getCurrentUser(){        ...    }}

使用时:

@AutowiredUserContext userContext;userContext.getCurrentUser();

这样做的好处:

1 可以依赖注入

2 可以做 AOP

3 可以做单元测试

4 可以替换实现

这就是 Spring 的优势

5、使用领域服务代替 BusinessUtil

很多项目会有这种类:

BusinessUtil

里面有:

calculateDiscount()checkOrderStatus()verifyUserPermission()

这是典型的 领域逻辑混乱

正确方式是:把逻辑放回领域。

例如:

DiscountServicePermissionServiceOrderDomainService

这样:

  • 职责清晰

  • 模块清晰

  • 可扩展

6、利用设计模式减少工具类

工具类泛滥,本质上是因为:缺少设计抽象。

几个常见替代模式:

1. 策略模式

例如不同折扣计算:

错误:

DiscountUtil.calculate(type)

正确:

DiscountStrategyVipDiscountStrategyNormalDiscountStrategy

2.工厂模式

例如对象创建:

错误:

ObjectUtil.createUser()

正确:

UserFactory.create()

3. 领域模型

例如订单逻辑:

错误:

OrderUtil.pay()

正确:

order.pay()

这是 领域驱动设计(DDD)思想

7、合理规划工具类包结构

如果项目确实需要工具类,建议进行分类管理。

例如:

util 
├──date
│   
└──DateUtils
├──string
│   └──StringUtils
├──file
│   └──FileUtils
└──crypto
     └──EncryptUtils

不要出现:

CommonUtilSystemUtilBusinessUtil

这些都是 设计失控的信号

8、判断标准

如果你写代码时准备新建工具类,可以问自己三个问题:

1.这个逻辑是不是业务逻辑?

如果是 → 放 Service。

2.这个逻辑是否需要依赖 Bean?

如果是 → 写 Spring Component。

3.这个逻辑是否纯粹通用?

如果是 → 才写 Util。

小结

工具类本身没有问题,但滥用工具类会破坏项目结构

在 Spring Boot 项目中,一个健康的结构应该是:

Controller   
↓Service   
↓Domain  /Repository

而工具类应该只扮演:底层能力库 的角色。

记住一句经验之谈:能写 Bean 就不要写 Util,能写领域对象就不要写静态方法。

        当代码真正按照职责划分时,项目会变得非常清晰—— 每个类都在做自己该做的事情。那时候再回头看那些 3000 行的 CommonUtil,会感觉像是程序员成长路上的“化石”。

-END-

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐