面向对象的防腐层(ACL)是在基础设施层定义的、职责明确且可替换的协作机制,通过接口抽象外部依赖,封装调用细节并转换为领域语言,确保外部变更不影响核心领域逻辑。
在 java 中实现面向对象的防腐层(acl),关键不是加一层“壳”,而是建立一套有边界、有职责、可替换的协作机制。它的目标很实在:让外部接口的任何变动——字段删了、状态码改了、返回 null 了、甚至整个服务下线——都不需要你去动订单、用户、库存这些核心领域类。
明确 ACL 的位置和角色
ACL 不是工具类,也不是通用拦截器,它是一个有明确上下文归属的协作对象。它应该:
- 定义在基础设施层,与 RestTemplate、FeignClient、DubboConsumer 等技术组件同级
- 对外暴露的是本限界上下文的语言(如
UserDTO、ShippingStatus),而不是外部系统的UserResponse或LogisticsCode - 内部封装所有与外部交互的细节:HTTP 调用、异常重试、空值兜底、字段映射、枚举对齐
用接口+实现分离内外契约
不要直接 new 一个 FeignClient 去用。先定义一个只讲业务的接口:
public interface LogisticsAcl {
ShippingInfo getShippingInfo(String orderId);
}
这个接口里没有 HTTP、没有 JSON、没有 LogisticsApiResponse。它只说“我要查一个运单信息”,返回的是你系统里能直接用的 ShippingInfo。然后才由具体实现类去对接那个“拼音缩写+魔法数字”的物流接口:
- 实现类里调用 Feign 或 Dubbo 客户端
- 把
LogisticsApiResponse映射成ShippingInfo,做非空校验、状态码翻译(比如把"1"转成ShippingStatus.DELIVERED) - 捕获网络异常、4xx/5xx,统一转为
ExternalServiceUnavailableException或返回兜底值
禁止外部模型渗入领域层
这是最容易破防的地方。检查你的代码里是否出现过这些情况:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 领域实体的属性类型是
com.external.xxx.UserResponse - 应用服务里直接 new 了一个
RestTemplate去调第三方 - 订单聚合根里写了
if ("Y".equals(remoteResult.getIsPaid()))
一旦发现,立刻把这段逻辑抽到 ACL 实现里。领域层只接收干净的 UserDTO、PaymentResult,只关心“用户是否有效”、“支付是否成功”,不关心对方用什么字段、什么值表示。
支持替换和演进
ACL 的接口设计要留出升级空间。例如物流接口从 HTTP 换成 Dubbo,或从自建系统换成云服务:
- 保持
LogisticsAcl接口不变 - 新增一个
DubboLogisticsAclImpl,复用相同的转换逻辑 - 通过 Spring 的
@Qualifier或配置切换实现类
这样换底层技术时,领域和应用层一行代码都不用改,真正实现“外部怎么变,我都不慌”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










