在现代企业级Java应用开发中,随着业务复杂度的持续增长,传统的MVC架构逐渐暴露出结构性缺陷。业务逻辑分散于Controller、Service甚至DAO层,导致系统演变为“大泥球(Big Ball of Mud)”架构。这种结构不仅使代码难以维护,还显著增加了新功能引入和缺陷修复的风险。
为应对这一挑战,阿里巴巴技术专家张建飞(Frank Zhang)提出了COLA架构——Clean Object-Oriented and Layered Architecture(整洁面向对象分层架构)。其核心使命是通过明确的分层设计与工程化实践,实现业务逻辑与技术细节的彻底解耦,从而有效控制软件复杂度。
COLA并非仅停留在理论层面,而是集架构思想、项目脚手架(Archetype)与可复用组件(Components)于一体的完整解决方案。自2018年首次发布以来,COLA已迭代至5.0版本,成为众多中大型企业治理复杂业务系统的首选范式。
本手册旨在为开发人员提供一份结构清晰、专业详实的COLA实践指南。内容涵盖架构解析、编码规范与典型应用场景,适合具备一定Java开发经验的工程师阅读与参考。建议读者结合官方GitHub仓库中的示例项目进行学习,以获得最佳理解效果。
COLA全称为Clean Object-Oriented and Layered Architecture,即“整洁面向对象分层架构”。它融合了整洁架构(Clean Architecture)、六边形架构(Hexagonal Architecture)与领域驱动设计(DDD)的核心思想,强调通过分层与依赖倒置来保障核心业务逻辑的独立性。
COLA的演进路径体现了从理念探索到工程落地的全过程:
COLA 1.0:初步建立四层分层模型,引入Command模式处理请求,解决业务逻辑组织问题。
COLA 2.0:采纳CQRS(命令查询职责分离)架构风格,尝试将读写操作解耦,提升高性能场景下的响应能力。
COLA 3.0:深度集成DDD战术设计,强化扩展点机制,支持多租户、多业务线共存场景。
COLA 4.0:重大架构重构,将框架拆分为Archetype(架构原型)与Components(功能组件)两部分,实现架构与工具的解耦。
COLA 5.0:全面支持JDK 17与Spring Boot 3.x,新增轻量级cola-archetype-light及单元测试增强组件。
该演进过程表明,COLA正逐步回归“架构即约束”的本质,弱化强制性框架绑定,转而提供更灵活、可渐进式采用的工程实践。
COLA的设计哲学围绕三大核心原则展开,这些原则共同构成了其架构稳定性的基石。
COLA严格区分业务复杂度与技术复杂度。前者指领域内的核心规则与流程,后者涉及数据库访问、缓存、消息中间件等具体实现。通过分层设计,确保业务逻辑集中于领域层,不受技术选型变更的影响。
遵循SOLID原则中的DIP,COLA规定高层模块(如领域层)不应依赖低层模块(如基础设施层),二者均应依赖抽象。具体表现为:领域层定义仓储接口(Repository Interface),由基础设施层提供其实现。这保证了领域核心的纯粹性与可测试性。
// 领域层定义接口
public interface UserRepository {
User findById(Long id);
void save(User user);
}
// 基础设施层实现
@Repository
public class UserRepositoryImpl implements UserRepository {
@Autowired
private UserMapper userMapper;
@Override
public User findById(Long id) {
UserDO userDO = userMapper.selectById(id);
return convertToEntity(userDO);
}
@Override
public void save(User user) {
UserDO userDO = convertToDataObject(user);
userMapper.insert(userDO);
}
}
COLA强制统一关键开发规范,包括:
DTO(Data Transfer Object)、Entity、DO(Data Object)之间的转换边界
包命名规则与目录结构
异常体系设计(BizException vs SysException)
此类标准化显著降低了团队协作的认知成本,使不同开发者产出的代码风格高度一致。
COLA可视为上述架构思想的“生产级实现”,既保留了理论优势,又提供了开箱即用的工具支持。
COLA采用标准的四层分层架构,各层职责分明,依赖关系为单向向下。
作为系统的流量入口,负责协议适配与参数解析。常见组件包括:
Controller:处理HTTP请求
Consumer:监听MQ消息
Scheduler:执行定时任务
✅ 推荐:仅做DTO与Command/Query对象的转换,不包含任何业务逻辑
⚠️ 注意:禁止在此层直接调用Mapper或Service实现类
扮演“业务编排中枢”角色,协调领域服务完成特定用例。主要职责包括:
事务控制(使用@Transactional)
权限校验与日志记录
调用领域服务并组装返回结果
核心组件为Executor(执行器),每个Executor对应一个Use Case,例如UserRegisterCmdExe专门处理用户注册流程。
系统的核心资产所在,封装所有核心业务逻辑。关键要素包括:
Entity:具有唯一标识的聚合根(Aggregate Root),包含业务行为方法
Value Object:描述属性特征的不可变对象
Domain Service:处理跨实体的业务逻辑
Domain Event:表示领域内发生的重要事件
Gateway Interface:定义对外部服务的访问契约
此层严禁依赖Spring Web、MyBatis等具体技术框架,仅允许依赖JDK与领域内其他元素。
承担“技术实现插件化”职责,具体实现领域层定义的接口。主要包括:
Repository Impl:基于MyBatis、JPA等ORM框架的数据持久化实现
Gateway Impl:调用第三方RPC或HTTP服务的具体实现
Config:外部配置加载
Message Producer/Consumer:消息中间件客户端封装
通过实现Repository与Gateway接口,完成对数据库、缓存、远程服务的技术对接。
为强化物理边界,COLA推荐使用Maven多模块构建项目。标准结构如下:
my-cola-app
├── my-cola-app-adapter/ # 适配器模块
├── my-cola-app-client/ # Client模块(API与DTO)
├── my-cola-app-app/ # 应用层模块
├── my-cola-app-domain/ # 领域层模块
└── my-cola-app-infrastructure/ # 基础设施层模块
各模块间依赖关系必须符合以下规则:
adapter → app, client
app → domain, client
domain → 无(仅依赖JDK)
infrastructure → domain, client
此结构通过Maven的<dependency>声明强制实施依赖约束,防止反向引用破坏架构完整性。
在模块划分基础上,COLA进一步提出双维度分包策略:纵向按领域划分,横向按功能分层。
例如,在订单域下,包结构应组织为:
com.company.order
├── adapter
│ ├── web
│ └── wap
├── app
│ ├── executor
│ └── service
├── domain
│ ├── model
│ ├── ability
│ └── gateway
└── infrastructure
├── gatewayimpl
└── mapper
该二维矩阵布局实现了高内聚与低耦合:
纵向:同一领域内的所有代码集中管理,便于理解和维护
横向:相同功能的组件归类存放,利于复用与替换
在COLA中,数据对象需经历清晰的转换链条:DTO → Entity → DO。每一层承担不同职责:
DTO:用于接口传输,位于client模块
Entity:内存中的领域对象,含业务行为
DO:数据库映射对象,仅含数据字段
为简化繁琐的手动转换,推荐使用MapStruct等编译期映射工具。
@Mapper(componentModel = "spring")
public interface UserAssembler {
UserAssembler INSTANCE = Mappers.getMapper(UserAssembler.class);
User fromDTO(UserRegisterCmd cmd);
UserRegisterCO toCO(User user);
UserDO toDO(User user);
User toEntity(UserDO userDO);
}
同时,可通过定义Assembler类集中管理转换逻辑,避免散落在各处。
扩展点是COLA最具特色的工程实现之一,完美体现“对扩展开放,对修改关闭”的开闭原则。
其核心由三部分构成:
ExtensionPoint:标记接口,定义业务扩展钩子
@Extension(bizId, useCase, scenario):注解标注扩展实现,三元组标识业务场景
ExtensionExecutor:执行器,根据上下文动态路由
// 定义支付方式扩展点
public interface PaymentExtPt extends ExtensionPoint {
void pay(Order order);
}
// 支付宝扩展实现
@Extension(bizId = "trade", useCase = "order", scenario = "alipay")
public class AlipayPaymentExtension implements PaymentExtPt {
@Override
public void pay(Order order) {
// 调用支付宝SDK
}
}
// 微信支付扩展实现
@Extension(bizId = "trade", useCase = "order", scenario = "wechat")
public class WechatPaymentExtension implements PaymentExtPt {
@Override
public void pay(Order order) {
// 调用微信支付API
}
}
调用时通过BizScenario指定具体场景:
@Resource
private ExtensionExecutor extensionExecutor;
public void processPayment(Order order, String channel) {
BizScenario scenario = new BizScenario("trade", "order", channel);
extensionExecutor.execute(PaymentExtPt.class, scenario, ext -> ext.pay(order));
}
该机制广泛应用于多渠道下单、差异化定价等业务场景,避免使用if-else或策略模式带来的维护难题。
当系统需要调用外部服务时,直接引入对方DTO会导致本领域被污染。为此,COLA引入Gateway作为防腐层。
以订单域调用商品服务为例:
// 订单域定义自己的上下文模型
public class Item {
private String title;
private BigDecimal price;
private Integer stock;
// getter/setter
}
// 定义网关接口
public interface ItemGateway {
Item getItemById(Long itemId);
}
// 实现网关,完成上下文映射
@Component
public class ItemGatewayImpl implements ItemGateway {
@Reference
private ItemService itemService; // 远程调用商品服务
@Override
public Item getItemById(Long itemId) {
ItemDTO remoteItem = itemService.queryById(itemId);
return convertToLocal(remoteItem); // 映射为本地模型
}
private Item convertToLocal(ItemDTO dto) {
Item item = new Item();
item.setTitle(dto.getTitle());
item.setPrice(dto.getPrice());
item.setStock(dto.getStock());
return item;
}
}
此举确保了本领域的语言一致性,并隔离了外部系统变更的影响。
COLA提供一系列可选组件,按需引入以提升研发效率。
这些组件均以Starter形式提供,可通过Maven坐标轻松集成。
本案例展示如何按照“自外向内”原则逐步构建用户注册功能。
Client层:定义UserRegisterCmd与UserServiceI接口
Domain层:创建User实体,实现密码加密行为
Infrastructure层:编写UserMapper与UserGatewayImpl
App层:实现UserRegisterCmdExe编排流程
Adapter层:编写UserController接收HTTP请求
// App层执行器
@Component
public class UserRegisterCmdExe {
@Autowired
private UserDomainService userDomainService;
@Transactional
public Response execute(UserRegisterCmd cmd) {
User user = userDomainService.register(cmd.getName(), cmd.getEmail(), cmd.getPassword());
return Response.buildSuccess(user.getId());
}
}
该流程清晰展示了各层协作方式:Adapter接收请求后,经App层编排,最终由Domain层完成核心逻辑。
本案例演示如何利用领域事件实现服务间解耦。
Order继承AggregateRoot,支付成功时发布OrderPaidEvent
InventoryHandler监听事件并扣减库存
LogisticsHandler创建物流单据
public class Order extends AggregateRoot {
public void pay() {
// ... 支付逻辑
this.registerEvent(new OrderPaidEvent(this.getId()));
}
}
@Component
public class InventoryHandler implements EventHandler<OrderPaidEvent> {
@Override
public void execute(OrderPaidEvent event) {
inventoryService.deductStock(event.getOrderId());
}
}
事件驱动模式提升了系统的可靠性与可扩展性,新增处理逻辑无需修改原有代码。
面对天猫、淘宝等不同业务线下单逻辑差异,扩展点机制可优雅解决。
@Extension(bizId = "tmall", useCase = "placeOrder", scenario = "default")
public class TmallPlaceOrderExtension implements PlaceOrderExtPt {
@Override
public void place(Order order) {
// 天猫专属逻辑:发放88VIP优惠券
}
}
@Extension(bizId = "taobao", useCase = "placeOrder", scenario = "default")
public class TaobaoPlaceOrderExtension implements PlaceOrderExtPt {
@Override
public void place(Order order) {
// 淘宝专属逻辑:计入淘金币
}
}
通过配置化路由,系统可在运行时动态选择合适的实现,满足灵活多变的业务需求。
✅ 渐进式重构:对于遗留系统,可先引入DTO与异常组件,再逐步迁移核心模块至领域层。
✅ 严格控制domain模块依赖:检查pom.xml,确保domain模块不引入spring-web、mybatis等技术依赖。
✅ 单元测试覆盖领域层:因领域层无外部依赖,非常适合编写高覆盖率的单元测试。
✅ 善用Archetype生成骨架:使用mvn archetype:generate快速创建符合规范的项目结构。
⚠️ 在Service中混合多种操作:如同时进行DB访问、缓存更新与MQ发送,违反关注点分离原则。
⚠️ 领域层依赖基础设施组件:如直接注入RedisTemplate或RabbitTemplate,破坏架构纯净性。
⚠️ 过度抽象导致复杂度上升:并非所有场景都需要建立完整的Entity与Repository,简单CRUD可适度简化。
合理评估项目复杂度,选择最适合的架构方案,才是工程实践的最高准则。
GitHub主仓库:https://github.com/alibaba/COLA
Wiki文档:https://github.com/alibaba/COLA/wiki
作者博客(CSDN):https://blog.csdn.net/significantfrank
阿里云开发者社区:https://developer.aliyun.com/article/923714
示例项目:https://github.com/alibaba/COLA/tree/master/cola-samples
# 生成Web应用
mvn archetype:generate \
-DgroupId=com.example \
-DartifactId=demo-web \
-Dversion=1.0.0-SNAPSHOT \
-Dpackage=com.example.demo \
-DarchetypeArtifactId=cola-framework-archetype-web \
-DarchetypeGroupId=com.alibaba.cola \
-DarchetypeVersion=5.0.0
DTO (Data Transfer Object):数据传输对象,用于接口间数据交换
DO (Data Object):数据对象,与数据库表结构一一对应
Entity:领域实体,内存中的业务对象,含状态与行为
VO (View Object):视图对象,用于前端展示
CO (Client Object):客户端对象,对外暴露的数据结构