分层架构(DAO/Mapper/Repository/Service/Controller/Manager)

一、体系总览

1.1 整体分层链路与上下游关系

这套组件是Java企业级开发(Spring生态为主)中,实现分层架构、职责解耦、代码复用的核心功能单元,完整的标准请求链路为:
客户端请求 → Controller → Service → Manager → Repository/DAO/Mapper → 数据库/第三方服务

各组件按职责分为4个核心层级,从上到下依赖关系单向传递,禁止反向依赖与跨层调用:

层级分类包含组件核心定位
入口层Controller系统对外门面,请求流量的入口与出口
业务层Service、Manager业务逻辑的核心承载,Service负责流程编排,Manager负责通用原子能力复用
数据访问抽象层Repository、DAO业务与数据存储的解耦层,Repository面向领域模型,DAO面向数据库表
数据访问实现层MapperORM框架对数据访问的具体实现,直接与数据库交互

1.2 贯穿全体系的核心设计原则

  1. 单一职责原则(SRP):每个组件仅负责一类固定职责,边界清晰,避免万能类
  2. 依赖倒置原则(DIP):上层仅依赖抽象接口,不依赖底层具体实现,实现解耦
  3. 开闭原则(OCP):对扩展开放,对修改关闭,通过接口抽象适配变化
  4. 迪米特法则:组件仅与直接相邻的组件交互,禁止跨层调用
  5. 关注点分离:业务逻辑、数据访问、请求处理、通用技术能力彻底分离,降低系统复杂度

二、各组件深度结构化拆解

2.1 Controller 层:请求入口与流量网关

核心定义:MVC架构中的控制器,是HTTP/RPC请求的系统对外门面,负责请求的接收、校验、路由与结果封装,是客户端与系统内部的唯一交互入口。

核心职责
  1. 请求接收与路由:匹配HTTP方法与URL路径,接收路径变量、请求体、查询参数等
  2. 基础参数校验:完成非空、格式、长度、范围等无业务属性的参数合法性校验(JSR-380规范)
  3. 协议转换:将请求参数转换为业务层所需的DTO对象,将业务结果封装为统一响应体
  4. 流量与安全前置:完成鉴权、限流、黑白名单等前置校验,兜底异常处理
  5. 特殊请求处理:支持异步请求、文件上传下载、WebSocket等场景
设计原则与规范
  • 瘦Controller原则:绝对不包含业务逻辑,仅做请求转发与结果封装
  • 无状态原则:单例无状态,禁止定义可变成员变量
  • 统一响应原则:所有接口返回统一格式的响应体,异常统一封装转换
典型实现与误区
  • 典型实现:Spring MVC的@RestController/@Controller注解
  • 高频误区:在Controller中编写业务逻辑、直接调用DAO/Mapper跨层访问、参数校验缺失、原始异常直接抛出
边界关系
  • 上游:客户端(浏览器、APP、第三方服务)
  • 下游:仅依赖Service层接口,禁止依赖更下层组件

2.2 Service 层:核心业务逻辑编排层

核心定义:系统业务能力的核心载体,是连接入口层与数据访问层的桥梁,负责核心业务规则实现、业务流程编排与事务控制。

核心职责
  1. 核心业务规则实现:封装业务领域的核心规则与校验(如“下单时余额需大于订单金额”)
  2. 业务流程编排:按业务场景编排多个原子操作的执行顺序(如下单全流程)
  3. 事务管理:定义事务边界,保证多数据操作的原子性(Spring @Transactional
  4. 依赖调度:调用Manager层通用能力、Repository/DAO层数据访问能力完成业务
  5. 业务异常处理:抛出业务规则校验异常,由Controller层统一封装返回
设计原则与规范
  • 厚Service薄Controller原则:核心业务逻辑必须下沉到Service层
  • 单一职责:一个Service类仅负责一个业务领域,避免万能Service
  • 面向接口编程:必须定义接口,上层仅依赖接口,不依赖实现类
  • 无状态原则:单例无状态,禁止定义可变成员变量
典型实现与误区
  • 典型实现:Spring @Service注解,采用接口+实现类模式
  • 高频误区:Service类代码臃肿、包含基础参数校验、直接操作数据库/第三方接口、事务控制不当(大事务、事务失效)、重复代码未下沉复用
边界关系
  • 上游:仅被Controller层依赖,禁止反向依赖Controller
  • 下游:依赖同领域其他Service接口、Manager层接口、Repository/DAO层接口

2.3 Manager 层:通用原子能力封装层

核心定义:Service层的“原子能力工具箱”,位于Service层之下、数据访问层之上,用于解决多Service通用逻辑复用、第三方系统交互隔离、复杂数据操作封装等问题,中小项目可省略,中大型/微服务项目强烈建议引入

核心职责
  1. 通用逻辑复用:封装多Service共用的原子逻辑(如缓存操作、分布式锁、幂等处理、通用数据查询)
  2. 外部依赖隔离:封装第三方系统/中间件调用(支付网关、短信服务、Redis、MQ、RPC调用),屏蔽底层实现变化
  3. 复杂数据操作封装:封装跨多Mapper的复杂查询、批量操作、数据聚合,避免Service层直接操作多Mapper
  4. 技术能力兜底:统一实现重试、熔断降级、容错、日志埋点等非业务技术代码
设计原则与规范
  • 原子性原则:方法仅做一件事,无业务流程编排,业务编排必须在Service层
  • 通用性原则:仅被单个Service使用的逻辑禁止放入Manager层
  • 无事务原则:不控制事务边界,仅被Service层的事务包含
  • 隔离性原则:对上层屏蔽底层技术细节,实现依赖解耦
典型实现与误区
  • 典型实现:Spring @Component注解,如UserManagerCacheManagerSmsManager
  • 高频误区:与Service职责混淆、在Manager中编写业务流程、反向依赖Service、与Mapper职责重叠、控制事务
边界关系
  • 上游:仅被Service层依赖,禁止被Controller直接调用
  • 下游:依赖DAO/Mapper/Repository、第三方系统、中间件

2.4 Repository 层:DDD领域驱动仓储层

核心定义:DDD(领域驱动设计)的核心组件,是面向领域聚合根的对象集合管理抽象,以“集合”的语义管理聚合根生命周期,彻底屏蔽底层存储细节,实现领域模型与数据存储的解耦。

核心职责
  1. 聚合根生命周期管理:仅负责聚合根的新增、修改、删除、查询,保证聚合根的完整性与不变性
  2. 对象映射转换:实现领域对象(DO)与持久化对象(PO)的双向转换,隔离领域模型与数据库表结构
  3. 存储细节屏蔽:对领域层完全屏蔽底层存储实现(MySQL、Redis、MongoDB等)
  4. 集合语义封装:接口设计采用add()remove()getById()等集合操作语义,而非数据库CRUD语义
  5. 领域规则保障:保证聚合根的业务不变量在持久化/查询时不被破坏
设计原则与规范
  • 聚合根原则:一个Repository仅对应一个聚合根,聚合内部实体禁止独立创建Repository
  • 依赖倒置:Repository接口放在领域层,实现类放在基础设施层,领域层仅依赖接口
  • 无业务逻辑原则:禁止在Repository中编写业务规则,业务逻辑必须在领域层实现
典型实现与误区
  • 典型实现:Spring Data JPA Repository接口,DDD架构中接口位于domain层,实现位于infrastructure层
  • 高频误区:把Repository当成DAO使用、接口设计面向数据库CRUD、给非聚合根创建Repository、领域层依赖实现类、直接暴露PO对象给领域层
边界关系
  • 上游:被领域层的领域服务、应用服务(对应传统Service)依赖
  • 下游:依赖底层DAO/Mapper、ORM框架、数据库,屏蔽存储细节

2.5 DAO 层:传统数据访问对象层

核心定义:传统三层架构中数据访问层的经典抽象,是Data Access Object(数据访问对象)设计模式的落地,用于封装数据库操作,隔离业务层与数据存储层。

核心职责
  1. 数据库操作封装:封装单表的CRUD操作,一个DAO对应一张数据库表
  2. 数据访问细节隔离:屏蔽JDBC连接、SQL执行、结果集处理、异常转换等底层细节
  3. SQL与代码分离:管理SQL语句,将SQL与Java业务代码解耦
  4. 结果集映射:将数据库结果集转换为PO对象,反之亦然
  5. 异常转换:将底层SQLException转换为统一的数据访问异常,屏蔽数据库厂商差异
设计原则与规范
  • 单表原则:一个DAO仅对应一张表,禁止多表操作
  • 无业务逻辑原则:仅做数据访问操作,绝对不包含业务逻辑
  • 面向接口编程:定义DAO接口,业务层依赖接口,不依赖实现类
典型实现与误区
  • 典型实现:基于JDBC、Spring JdbcTemplate的DAO模式,Hibernate DAO实现
  • 高频误区:在DAO中编写业务逻辑、一个DAO操作多张表、业务层直接写SQL跳过DAO层
边界关系
  • 上游:被Service/Manager层依赖,禁止反向依赖上层
  • 下游:直接操作数据库,基于JDBC/数据库连接池实现

2.6 Mapper 层:ORM映射数据访问实现层

核心定义:以MyBatis为代表的ORM框架对DAO模式的现代化、轻量化实现,是DAO层的主流落地形态,通过注解/XML配置SQL与Java方法的映射,自动处理参数绑定与结果集映射,消除传统DAO的重复模板代码。

核心职责
  1. SQL映射:通过接口方法+XML/注解,映射对应的SQL语句,实现数据库CRUD
  2. 自动参数绑定:自动将方法参数绑定到SQL占位符,处理类型转换
  3. 结果集自动映射:自动将查询结果映射为PO对象,支持一对一、一对多等复杂映射
  4. 动态SQL管理:提供动态SQL能力,简化复杂条件查询的编写
  5. 缓存管理:提供一级/二级缓存,优化查询性能
设计原则与规范
  • 单表原则:一个Mapper接口对应一张数据库表
  • 无业务逻辑原则:仅做数据访问,禁止包含业务逻辑
  • SQL与代码分离:复杂SQL建议写在XML文件中,与Java接口分离
  • 细粒度原则:方法粒度要细,避免一个方法对应超级复杂SQL,降低复用性
典型实现与误区
  • 典型实现:MyBatis @Mapper注解,Mapper接口+XML映射文件,MyBatis-Plus BaseMapper
  • 高频误区:编写复杂多表关联SQL导致维护困难、在Mapper中处理业务逻辑、滥用嵌套映射引发N+1查询问题、跨层调用跳过Mapper直接执行SQL
边界关系
  • 上游:被DAO实现类、Manager、Service层依赖
  • 下游:基于ORM框架封装JDBC,直接操作数据库

三、核心易混淆组件横向对比

3.1 DAO vs Mapper vs Repository 深度对比

对比维度DAO(数据访问对象)Mapper(ORM映射)Repository(DDD仓储)
架构定位传统三层架构的数据访问抽象DAO模式的ORM具体实现DDD架构的领域存储抽象
设计思想面向数据库表,封装单表CRUD面向SQL映射,简化JDBC模板代码面向领域聚合根,模拟集合语义
操作对象数据库表对应的PO对象数据库表对应的PO对象领域层的聚合根DO对象
接口语义面向数据库:insert、update、delete同DAO,轻量化SQL映射面向集合:add、remove、get、find
核心目标隔离业务层与数据库消除DAO模板代码,简化数据访问隔离领域层与存储,实现领域模型解耦
与业务耦合与业务逻辑解耦,仅关注数据操作与业务逻辑解耦,仅关注SQL映射与领域模型强绑定,与业务语义对齐
典型场景传统JDBC项目、轻量级项目绝大多数MyBatis/MyBatis-Plus项目DDD架构、复杂业务领域项目

3.2 Service vs Manager 边界对比

对比维度Service层Manager层
架构定位核心业务逻辑编排层,业务能力核心通用原子能力封装层,Service的工具箱
核心职责实现业务规则、编排业务流程、控制事务边界封装通用逻辑、第三方调用、中间件操作、复杂数据聚合
设计原则面向业务场景,一个Service对应一个业务领域面向通用能力,一个Manager对应一类原子能力
代码特性包含业务流程、多步骤编排、业务规则校验原子性、无业务流程、高复用性、无事务控制
事务控制事务边界的定义者,负责事务的开启与回滚不控制事务,仅被事务包含,可跨事务复用
复用性业务场景专属,复用性低通用能力,可被多Service调用,复用性高
依赖方向依赖Manager、Mapper、同领域其他Service仅依赖Mapper、第三方系统、中间件,禁止依赖Service
是否必须分层架构核心必选层非必须,中小项目可省略

四、全链路调用流程与架构适配

4.1 标准全链路执行流程

  1. 客户端发送HTTP请求,经过过滤器/拦截器完成认证、鉴权等前置处理
  2. 请求路由到Controller层,完成参数校验、协议转换
  3. Controller调用Service层接口,传入DTO参数
  4. Service层完成业务规则校验,编排业务流程,控制事务边界
  5. Service调用Manager层的通用原子能力,完成缓存、第三方调用、复杂数据查询等操作
  6. Manager/Service调用Mapper/DAO/Repository层,执行数据库操作
  7. 结果沿原链路逐层返回,最终由Controller封装为统一响应体返回给客户端

4.2 不同架构体系下的组件适配

  1. 传统MVC三层架构

    • 表现层:Controller
    • 业务层:Service
    • 数据访问层:DAO/Mapper
    • 适配:可省略Manager层,适合轻量级、业务简单的项目
  2. DDD领域驱动四层架构

    • 用户接口层:Controller
    • 应用层:ApplicationService(对应传统Service,仅做流程编排)
    • 领域层:DomainService(核心业务规则)、Repository接口
    • 基础设施层:Repository实现类、Mapper、Manager通用能力
    • 适配:以Repository为核心数据访问抽象,Mapper作为底层实现,适合复杂业务的中大型项目
  3. 微服务分布式架构

    • 网关层:统一入口,替代Controller的鉴权、限流能力
    • 接口层:Controller(RESTful接口)、RPC API接口
    • 业务层:Service(业务编排)、Manager(封装RPC调用、分布式锁、分布式事务等分布式能力)
    • 数据访问层:Repository/Mapper(适配分库分表、读写分离)
    • 适配:放大Manager层的作用,实现分布式能力的统一封装与复用

五、最佳实践与避坑指南

5.1 业界通用最佳实践

  1. 严格遵守分层边界:禁止跨层调用,严格遵循单向依赖规则
  2. 分层校验原则:Controller做基础格式校验,Service做业务规则校验,Mapper层不做校验
  3. 数据对象隔离:PO仅在数据访问层使用,DTO用于前后端传输,禁止PO直接暴露给前端,通过MapStruct等工具实现对象转换
  4. 事务精准控制:事务边界仅在Service层定义,事务内禁止RPC调用、缓存操作等非数据库操作,避免大事务
  5. 代码复用规范:多Service通用逻辑下沉到Manager层,多Manager通用逻辑封装为工具类,禁止复制粘贴重复代码
  6. 代码行数管控:Controller建议≤300行,Service≤500行,Manager≤300行,Mapper≤200行,避免单类过度臃肿

5.2 高频错误避坑指南

  1. 分层混乱跨层调用:禁止Controller直接调用Mapper,即使简单CRUD也要经过Service层,便于后续业务扩展
  2. 职责错位代码臃肿:禁止Controller写业务逻辑、Service写通用技术代码,严格遵循“瘦Controller、厚Service、通用Manager”
  3. 事务控制失效:避免非public方法加@Transactional、异常被捕获不抛出、事务内执行非数据库操作等场景
  4. SQL滥用性能问题:Mapper以单表查询为主,避免过度多表关联与嵌套映射,防止N+1查询问题
  5. 对象混用安全风险:禁止PO对象直接返回给前端,避免数据库表结构泄露、敏感字段暴露
  6. Repository与DAO混淆:DDD项目中必须严格遵守Repository的聚合根原则与集合语义,禁止将Repository退化为DAOe

更多推荐