MyBatis-Plus中 IService 与 ServiceImpl等内容的深入思考理解
1️⃣ 基本概念
名称 | 类型 | 作用 |
---|---|---|
IService<T> | 接口(Interface) | 定义通用 CRUD 操作及可扩展业务方法的契约,是业务层抽象接口 |
ServiceImpl<M extends BaseMapper<T>, T> | 抽象类(Abstract Class) | 提供 IService 的默认实现,包括基本 CRUD、分页、Lambda 查询等逻辑 |
UserService | 接口 | 继承 IService<User> ,可新增特定业务方法(如 findByEmail ) |
UserServiceImpl | 类 | 实现 UserService ,实际执行逻辑(可直接调用 DB、加缓存等) |
2️⃣ Controller 依赖对比
1. 直接依赖实现类 (ServiceImpl
)
@Autowired
private UserServiceImpl userService;
- Controller 写死依赖具体实现类
- 换实现类时(如
UserServiceCacheImpl
),Controller 必须修改 - 耦合度高,扩展性差
2. 依赖接口 (IService
/ UserService)
@Autowired
private UserService userService;
- Controller 只依赖接口,不关心具体实现
- Spring 容器可注入不同实现类(
@Primary
或@Qualifier
) - 实现类可随时替换,Controller 不需改动
- 符合面向接口编程原则,解耦、易测试、易扩展
3️⃣ Spring 注入机制
场景 | 说明 |
---|---|
容器中只有一个实现类 | Spring 自动注入 |
有多个实现类 | 可通过 @Primary 指定默认注入,或 @Qualifier 精确注入 |
配置切换实现 | 可使用条件注解 (@ConditionalOnProperty ) + 配置文件切换,实现无代码修改替换实现 |
4️⃣ 调用接口外的方法
- 推荐方式:在接口中声明方法 → 实现类实现 → Controller 调用
- 不推荐方式:强制转换为实现类调用(
((UserServiceImpl) userService).customMethod()
) - 原因:强制转换破坏了接口解耦,降低可维护性和测试性
5️⃣ 与接口继承关系对应
IService<T>
是接口,定义抽象契约- 业务接口(如
UserService
)继承IService<T>
:interface UserService extends IService<User>
- 实现类(
UserServiceImpl
)实现接口:class UserServiceImpl implements UserService
- UML 表达:
IService<T> (接口)↑UserService (接口)↑
UserServiceImpl (类)
- Controller 依赖接口(
UserService
),实现类在 Spring 容器中注入
6️⃣ 总结要点
- IService:抽象契约,提供通用方法,面向接口编程
- ServiceImpl:实现
IService
的抽象类,提供通用业务实现 - 依赖接口而非实现类:Controller 代码解耦、可替换、易测试
- 接口继承:子接口继承父接口方法(
extends
),实现类实现接口(implements
) - 接口外方法调用:最好通过接口声明扩展,避免类型强转
✅ 一句话概括:
Controller 依赖
IService
接口,而ServiceImpl
提供默认实现,接口继承 (extends
) 构建契约层次,实现类 (implements
) 执行具体逻辑,这种结构实现了解耦、灵活、可替换的业务设计。