MyBatis-Plus 原理解析
其实 MyBatis-Plus 的 Service 层设计就是为了让开发者不用重复写很多样板代码。我们来一点点剖析 UserServiceImpl
、IService
、UserService
、ServiceImpl
之间的关系和调用链。
1. 类/接口关系图
IService<T>
▲
│
UserService (接口) <-- 自定义的接口
▲
│
ServiceImpl<M, T> (抽象类,提供默认实现)
▲
│
UserServiceImpl (写的实现类)
2. 各个角色的作用
(1) IService<T>
- MP 提供的 通用 Service 接口,定义了最常用的 CRUD 方法。
- 例如:
public interface IService<T> {
boolean save(T entity);
boolean removeById(Serializable id);
boolean updateById(T entity);
T getById(Serializable id);
List<T> list();
// ... 还有很多
}
(2) UserService
- 你的业务接口,继承了
IService<User>
。 - 这样
UserService
就自动拥有了所有 CRUD 方法,不用自己再声明。 - 但你也可以在里面 加自定义业务方法:
public interface UserService extends IService<User> {
User findByEmail(String email); // 自定义方法
}
(3) ServiceImpl<M, T>
- MP 提供的 通用实现类,实现了
IService<T>
里的所有方法。 - 内部通过调用
BaseMapper<T>
来完成数据库操作。
源码片段(简化):
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
@Autowired
protected M baseMapper; // Mapper 注入进来
@Override
public boolean save(T entity) {
return baseMapper.insert(entity) > 0;
}
@Override
public T getById(Serializable id) {
return baseMapper.selectById(id);
}
}
(4) UserServiceImpl
- 你的实现类,继承了
ServiceImpl<UserMapper, User>
并实现UserService
。 - 因为
ServiceImpl
已经实现了IService
的方法,所以你啥都不用写,就自动拥有save
、getById
、list
等方法。 - 你可以在里面实现自定义的业务逻辑:
@Service
public class UserServiceImpl
extends ServiceImpl<UserMapper, User>
implements UserService {
@Override
public User findByEmail(String email) {
return lambdaQuery().eq(User::getEmail, email).one();
}
}
3. 调用链条
比如调用 userService.save(user)
的时候,流程是这样的:
- Controller 调用:
userService.save(user);
- Spring 容器注入的其实是
UserServiceImpl
对象。
所以进入UserServiceImpl.save()
。 UserServiceImpl
继承自ServiceImpl
,没有重写save()
,于是调用的是ServiceImpl.save()
。ServiceImpl.save()
内部会调用baseMapper.insert(user)
,而baseMapper
是注入的UserMapper
,继承了BaseMapper<User>
。BaseMapper
底层最终由 MyBatis 执行 SQL,完成插入操作。
4. 关键总结
IService<T>
:定义通用方法(接口)。UserService
:业务接口,扩展IService<User>
。ServiceImpl<M, T>
:默认实现,帮你实现了IService
的所有方法。UserServiceImpl
:实现类,继承ServiceImpl
,可以直接用 CRUD,也可以扩展业务方法。
所以:
👉 写的代码只需要关心业务逻辑,CRUD 全交给 MyBatis-Plus 的基类完成。