前言
最近看到网络上五花八门的后台管理系统的框架,我打算简单手搓一个属于自己的前后端框架。已经动工有一段时间了,后端使用的springboot+mybatis-plus。最开始service层的各个服务都是用的mybatisx自动生成的service。形如:
css
|--service
|--impl
|--userServiceImpl
|--roleServiceImpl
|--userService
|--roleService
这样的话,要实现userService的具体业务,比如对user进行role权限的校验,那就必须要向userService注入roleService。
如果项目小的话还好,项目一旦大起来,各种表之间的service互相注入,很容易就会造成循环依赖的问题,而且内部方法也是杂乱无章。
为了解决这个问题,我决定开始重构代码
重构方案
我将我的service内部再分层,分作了三层分层架构
css
|--service
|--basic
|--domain
|--facade
那么这三层架构各自具体负责什么,下面我们具体说明
basic - 基础服务层
basic层就是存放原本mybatisx生成的所有service,它的职责就是
- 提供最基础的CRUD操作
- 直接与数据访问层(Mapper)交互
- 实现单表的基本业务逻辑
并且,它不能注入别的basicService
domain - 领域服务层
domain用来实现具体的业务逻辑,可以任意注入组合basicService以实现复杂的业务。
我对domain层里具体的domainService有自己的一套划分和命名规则。我们以用户模块为例,我会将其划分为3个domainService:
css
|--domain
|--impl # 实现类
|--UserQueryDomain # 用户有关的查询业务逻辑
|--UserOperationDomain # 用户有关的操作业务逻辑
|--UserValidationDomain # 用户有关的校验业务逻辑
facade - 门面服务层
facade层用以提供统一的对外服务接口,Controller层直接注入facade依赖就好,用以整合协调不同Domain的服务。包含操作权限的验证,业务流程的高层协调。具体我是直接以模块划分和命名的:
css
|--facade
|--impl # 实现类
|--UserFacade # 用户模块门面
|--RoleFacade # 角色模块门面
例如我有一个addUser方法,我在UserFacade中要先调用UserValidationDomain校验用户名是否已存在,再调用UserOperationDomain的添加用户。
总结
这样做,我们的service三层各司其职,修改基础功能也不会影响上层业务逻辑。
依赖因为有了方向性,所以也避免了循环依赖的问题。
rust
facade -> domain -> basic
而且复用性提高了,Basic层可被多个Domain复用,Domain层可被多个Facade复用。