目前,Java 后端架构主要采用 SpringBoot 框架的单体架构。对于 SpringBoot 项目,其技术栈和实现方案已经相当成熟。系统通常采用 MVC 分层架构,从下到上依次为持久层、业务层和控制层(展示层在前端,此处不详述)。持久层负责与数据库交互,完成数据的持久化存储;业务层负责实现具体的业务逻辑,处理来自控制层的请求,并调用持久层接口操作数据;控制层作为前后端的交互层,负责接收和处理前端请求,并将其分发给相应的业务层处理。
这种分层方式清晰简单,现在大多数项目都采用这种方式。但现在这种架构有一个普遍的做法:业务层 Service 的实现通常与实体一一对应,即每个实体都对应一个持久层的 Mapper 和一个业务层的 Service,该实体相关的业务就在对应的 Service 中处理。然而,当需要处理涉及多个实体的复杂业务时,就需要调用多个 Service。
对于这种业务情况,大多数项目采用 Service 之间相互调用的方式来处理,这就会引发一些问题。首先,会造成代码耦合度高,一个 Service 的变动可能会影响到多个相关的 Service;其次,在进行单元测试时,由于 Service 之间的依赖关系,测试变得更加复杂;最后,多个 Service 之间的调用链路过长,会增加系统的复杂度和维护成本。这种做法难以复用,且容易导致代码混乱。
究其根本原因,对于复杂的业务逻辑,除了持久层、业务层、控制层之外,在业务层和控制层之间还应该有一个业务编排层,用来组织编排多个 Service 进行业务处理。但是,现有的系统架构中普遍缺少这一层设计,这就导致了上述问题。
然而,在系统中添加业务编排层也存在冗余的问题,因为大多数业务逻辑较为简单,原有业务层就足以处理,这就形成了一个两难选择。我本考虑在复杂业务模块中增加业务编排层,而在简单业务模块中保留原有分层。这种折衷方案虽然可行,但不够优雅,缺乏统一的设计理念,在后续维护中可能会导致一些混乱。
因此,我决定让控制层除了处理前端请求外,同时承担业务编排层的职责。对于复杂业务,将在 Controller 层组织编排多个 Service。后续会根据系统业务复杂度的发展再考虑如何重构优化,届时可能会借鉴 DDD 架构的思想进行重构。
所以,你会看到在目前的云行 AI 架构中,Controller 层负责前端请求的接收、参数校验的同时,在复杂业务场景下会负责组织编排多个 Service。并且,Service 层保持业务逻辑的原子性,禁止 Service 层之间互相调用。未来会根据业务发展情况,再考虑分层的最佳实践方案。
2025年5月9日