现代Java生态已弃用受检异常,DDD强调用前置校验、状态机约束和领域异常(RuntimeException)实现防错,而非依赖异常捕获;应通过限界上下文、事件驱动、Saga模式及结果对象等DDD原生手段保障一致性与可维护性。

这个问题混合了多个不兼容的技术范式和现实约束,需要先厘清关键矛盾点。
受检异常在现代Java生态中已基本弃用
Java自8版本起,官方明确建议避免使用受检异常(checked exception),Spring、Hibernate、JDK新API(如CompletableFuture、Stream)均统一采用运行时异常(RuntimeException)语义。编译强制抛出声明不仅增加调用方冗余代码,更与DDD强调的“表达领域意图”相冲突——异常应反映业务规则破坏(如运单超时不可撤销),而非技术故障(如数据库连接失败)。强行保留受检异常会污染领域层,使仓储接口暴露基础设施细节。
无锁防错网不是靠异常机制实现的
供应链运单系统中的“防错”,核心是前置校验与状态机约束,不是靠捕获异常来兜底:
- 用值对象封装运单号、承运商ID等关键字段,构造时即校验格式与合法性
- 定义明确的状态流转规则(如已揽收→运输中→派送中→签收完成),非法状态变更直接抛出领域异常(DomainException),且该异常继承RuntimeException
- 关键操作(如签收)需通过聚合根协调,内部校验库存、时效、权限三重约束,失败则拒绝状态变更,不依赖try-catch回滚
DDD重构超大型物流系统的真正抓手
针对运单这类高并发、强一致要求的子域,应聚焦以下可落地动作:
- 限界上下文切分:将“运单生成”“路由调度”“在途跟踪”“异常申诉”划为独立上下文,各自维护状态机与防腐层(ACL),避免跨上下文直接调用
- 事件驱动解耦:运单创建成功后发布OrderCreatedEvent,由调度上下文消费并触发路径规划,失败不阻塞主流程
- 最终一致性保障:对账、结算等非实时场景,用Saga模式补偿,而非同步事务+异常重试
-
防错内建于模型:例如运单聚合根中定义
canBeCancelledAt(LocalDateTime now)方法,返回布尔值而非抛异常;调用方根据返回值决定UI禁用或提示,逻辑清晰可测
替代“编译制约”的更有效手段
若目标是强制开发者处理特定业务风险,推荐以下DDD原生方案:
- 用Optional<DeliverySlot>代替可能为空的预约时间,迫使调用方显式处理“未预约”分支
- 将易错操作封装为返回结果对象(如
Result<Waybill, DeliveryError>),错误类型限定为预定义的领域错误枚举 - 在领域服务中使用断言(Assert.notNull)配合有意义的错误消息,测试阶段即可暴露逻辑漏洞


















