在使用 MyBatis-Plus 開發業務邏輯時,IService
和 ServiceImpl
是經常遇到的兩個核心類。很多初學者會疑惑:
- 為什么要定義
IService
? ServiceImpl
又解決了什么問題?- 它們之間到底有什么區別與聯系?
本文將結合源碼與應用場景,帶你徹底搞懂 IService 與 ServiceImpl 的區別。
1. IService 是什么?
IService<T>
是 MyBatis-Plus 提供的 通用業務接口,其中包含了常用的 CRUD 方法,比如:
save
—— 保存實體removeById
—— 根據 ID 刪除updateById
—— 根據 ID 更新getById
—— 根據 ID 查詢list
—— 查詢列表page
—— 分頁查詢
換句話說,IService
定義了通用的服務層規范。
使用示例
public interface UserService extends IService<User> {// 你可以在這里擴展業務專屬方法User findUserByEmail(String email);
}
這里 UserService
繼承了 IService<User>
,自動擁有了 CRUD 的能力。
2. ServiceImpl 是什么?
ServiceImpl<M, T>
是 MyBatis-Plus 提供的 IService 默認實現類,已經幫我們實現了大多數方法,避免了重復造輪子。
M
:具體的 Mapper 類型,例如UserMapper
T
:實體類型,例如User
它實現了 IService
接口,內部封裝了對 Mapper 的調用邏輯。
使用示例
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic User findUserByEmail(String email) {return lambdaQuery().eq(User::getEmail, email).one();}
}
這里 UserServiceImpl
繼承了 ServiceImpl
,再實現我們自定義的 UserService
,這樣就既擁有通用的 CRUD,又能編寫業務邏輯。
3. 區別與聯系
特性 | IService | ServiceImpl |
---|---|---|
定義 | 接口,定義了通用 CRUD 規范 | 實現類,提供了默認實現 |
泛型 | <T> 實體類 | <M, T> ,分別是 Mapper 和實體類 |
作用 | 抽象層,保證服務接口統一 | 具體實現,避免手寫重復代碼 |
擴展性 | 可以在子接口中定義業務方法 | 可以在子類中實現業務邏輯 |
是否必須 | 建議使用,利于解耦 | 通常需要,直接繼承即可 |
4. 常見使用方式
在項目中通常的結構是:
- 實體類
User.java
- Mapper 層
UserMapper extends BaseMapper<User>
- Service 接口層
UserService extends IService<User>
- Service 實現層
UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService
這樣,整個項目既保持了 MyBatis-Plus 的通用 CRUD,又能靈活擴展業務邏輯。
5. 為什么要區分 IService 和 ServiceImpl?
很多人可能會問:直接寫 ServiceImpl
不就夠了嗎?
原因在于:
- 接口分離:
IService
讓我們在業務層面編程時,可以面向接口,而不是依賴實現類。 - 可擴展性:當我們需要切換實現方式(比如緩存+DB、多數據源),只需要改實現類,而不影響接口層調用。
- 解耦:接口與實現分離是面向對象設計的基本原則。
6. 總結
-
IService
:定義了 CRUD 的接口規范,是抽象層。 -
ServiceImpl
:提供了IService
的默認實現,是具體實現層。 -
通常做法:
UserService extends IService<User>
UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService
這樣既能享受 MyBatis-Plus 的便捷,又能保證業務邏輯清晰解耦。
👉 簡而言之:
IService
= 規范,ServiceImpl
= 實現。
兩者搭配使用,才是 MyBatis-Plus 推薦的最佳實踐。