do仅承载状态且与持久化绑定,bo封装行为并依赖do,service仅协调编排,实体间通过组合与事件松耦合。

关键在于把“是什么”和“能做什么”彻底分开——DO 负责承载状态,BO 负责驱动行为,两者协作但不混杂。
DO 只表达领域状态,不做任何业务判断
Domain Object(DO)是领域模型的静态快照,它只描述结构和数据,不包含业务规则或流程逻辑。
- 字段全部设为 protected 或 private,配带校验的 getter/setter(如 setOrderStatus() 内部检查状态合法性)
- 不写 cancel()、applyDiscount() 这类方法;只保留基础操作,如 setStatus(String s),且仅做格式/非空校验
- 与持久化强绑定:JPA 实体注解(@Entity、@Table)只出现在 DO 上,Repository 也只操作 DO
- 构造函数强制初始化核心字段(如 orderId、createTime),避免半成品对象
BO 封装完整业务行为,依赖 DO 但不继承它
Business Object(BO)是领域行为的执行主体,它持有 DO 实例,通过调用 DO 的受控接口完成状态变更,并封装规则、流程、策略等动态逻辑。
- BO 不是 DO 的子类,也不含 @Entity 注解;它是一个普通 Java 类,生命周期由 Service 管理
- 典型方法如 placeOrder()、refundIfEligible()、generateInvoice(),内部组合多个 DO 操作 + 外部服务调用 + 条件分支
- BO 可注入策略(如 DiscountStrategy)、事件发布器(如 OrderPlacedEvent)、校验器(如 InventoryChecker)
- 测试友好:可直接 new BO(new OrderDO(...)),无需数据库或 Spring 上下文
Service 层只作为协调者,不写业务逻辑
Service 不再是“万能胶”,而是轻量级编排层,职责明确为:组装 BO、传递 DO、触发事务、处理异常边界。
- Controller → Service → BO → (DO + 外部服务) → 返回结果
- Service 方法签名应返回 BO 或 void,不直接返回 DO;DO 仅在 BO 内部流转
- 事务控制放在 Service 方法上(@Transactional),但状态变更逻辑必须下沉到 BO 中
- 避免在 Service 中写 if-else 判断订单能否取消——这个判断应封装在 BO.cancel() 里
分层协作要靠接口隔离,而非继承或强引用
实体之间不靠父子继承表达业务关系,而用组合+接口+事件来松耦合协作。
- 订单与商品不是 “Order is-a Product”,而是 “Order has-a List
”,用组合而非继承 - 跨域协作不用 Service 直接调用另一个模块的 Service,而是发布领域事件(如 OrderPaidEvent),由监听器处理积分、通知、库存扣减
- 需要多态时用接口定义行为契约(如 PacketProcessor
),而非抽象类继承 - BO 和 DO 之间通过构造参数或工厂方法建立单向依赖,DO 不感知 BO 存在
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











