面向对象的防腐层(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 Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
立即学习“Java免费学习笔记(深入)”;
- 领域实体的属性类型是
com.external.xxx.UserResponse - 应用服务里直接 new 了一个
RestTemplate去调第三方 - 订单聚合根里写了
if ("Y".equals(remoteResult.getIsPaid()))
一旦发现,立刻把这段逻辑抽到 ACL 实现里。领域层只接收干净的 UserDTO、PaymentResult,只关心“用户是否有效”、“支付是否成功”,不关心对方用什么字段、什么值表示。
支持替换和演进
ACL 的接口设计要留出升级空间。例如物流接口从 HTTP 换成 Dubbo,或从自建系统换成云服务:
- 保持
LogisticsAcl接口不变 - 新增一个
DubboLogisticsAclImpl,复用相同的转换逻辑 - 通过 Spring 的
@Qualifier或配置切换实现类
这样换底层技术时,领域和应用层一行代码都不用改,真正实现“外部怎么变,我都不慌”。

















