分层架构(Layered Architecture)是所有架构模式的起点——Spring Boot 默认的三层(Controller/Service/Dao)就是它,六边形、洋葱、整洁架构也都是从它演化来的。这篇把它讲清楚:为什么要分层、分层的规则、以及它遗留了什么问题(这些问题正是后续架构要解决的)。
一、解决什么问题:代码没有结构
不分层的系统,代码是"一坨"的:一个方法里,HTTP 请求处理、业务判断、SQL 执行全混在一起。结果是——改数据库要动到界面代码,改界面又担心碰坏业务逻辑,牵一发动全身。
分层架构的思路:按"职责"把代码切成几层,每层只管一件事。
二、三层结构
经典的分层是三层(也是 Spring Boot 的默认结构):
| 层 | 职责 | Spring 里 |
|---|---|---|
| 表现层(Presentation) | 处理 HTTP 请求、参数校验、返回响应 | @Controller |
| 业务层(Business) | 业务逻辑、事务 | @Service |
| 持久层(Persistence) | 数据库读写 | @Mapper / @Repository |
java
@Controller // 表现层:只处理 HTTP
public class OrderController {
@GetMapping("/order/{id}")
public Order detail(@PathVariable Long id) {
return orderService.getById(id); // 调业务层
}
}
@Service // 业务层:只做业务逻辑
public class OrderService {
public Order getById(Long id) {
// 业务逻辑:校验、计算...
return orderMapper.selectById(id); // 调持久层
}
}
@Mapper // 持久层:只做数据库读写
public interface OrderMapper {
Order selectById(Long id);
}三、分层规则
分层的核心规则是依赖单向向下:
表现层 → 业务层 → 持久层
(上层依赖下层,不能反向、不能跨层)- 上层可以调下层:Controller 调 Service,Service 调 Mapper
- 不能反向:Mapper 不能调 Service(持久层不该知道业务)
- 尽量不跨层:Controller 不该直接调 Mapper(要经过 Service 处理业务)
这条规则保证"每层只依赖下面一层",依赖关系清晰、可替换。
四、分层架构的问题(引出后续架构)
分层架构用了很多年,但它有个结构性的问题:业务层依赖持久层,也就是业务逻辑依赖数据库。
java
@Service
public class OrderService {
// 业务层直接依赖 Mapper(持久层)→ 业务被数据库"绑架"了
private final OrderMapper orderMapper;
}这带来两个麻烦:
- 换数据库困难:业务层代码里到处是 Mapper,想从 MySQL 换 PostgreSQL、或换 ORM 框架,业务代码要跟着动
- 业务逻辑难测试:想单测
OrderService的业务逻辑,必须连数据库,测试又慢又脆
核心问题一句话:业务层直接依赖了数据库的具体实现(Mapper),违反了依赖倒置原则——高层(业务)不应该依赖低层(数据库),两者都应该依赖抽象。正确做法是业务层定义接口 OrderRepository,业务依赖这个接口、数据库的实现也实现这个接口,让业务和数据库都依赖抽象,谁都不直接依赖谁。
这正是六边形架构、洋葱架构、Clean Architecture 要解决的:用"依赖倒置"把依赖方向反过来,让业务层在中心、数据库和框架在外圈(见《六边形与洋葱架构》)。
小结
- 分层架构按职责切层(表现/业务/持久),是架构的起点
- 规则:依赖单向向下,上层调下层,不反向不跨层
- Spring Boot 三层就是分层架构的落地
- 遗留问题:业务层依赖持久层(业务被数据库绑架)→ 引出六边形/洋葱/整洁
下一步看《六边形与洋葱架构》——它们用"依赖倒置"解决分层架构"业务依赖数据库"的问题,让业务核心彻底独立。
