待解決
//TODO 面試題
為啥mybatis的mapper只有接口沒有實現類,但它卻能工作??(ai參考,待深究源碼)
1. 動態代理生成代理對象
MyBatis 使用 JDK 動態代理 為每個 Mapper 接口生成代理對象: ? 核心類:MapperProxy
(實現 InvocationHandler
接口)和 MapperProxyFactory
(代理工廠)。 ? 代理對象創建流程:
-
當調用
SqlSession.getMapper(UserMapper.class)
時,MyBatis 會通過MapperProxyFactory
創建代理對象。 -
MapperProxy
作為代理邏輯處理器,攔截所有接口方法的調用。 -
代理對象通過
Proxy.newProxyInstance
動態生成,無需手動編寫實現類。
2. 方法調用與 SQL 執行的映射
代理對象攔截方法調用后,通過以下步驟執行 SQL: ? 步驟 1:解析方法簽名 根據接口全限定名(如 com.example.UserMapper
)和方法名(如 getUserById
),生成唯一的 方法 ID(例如 com.example.UserMapper.getUserById
)。
? 步驟 2:綁定 SQL 語句 MyBatis 啟動時會加載 XML 文件,將 <mapper>
標簽的 namespace
與接口全限定名匹配,并通過方法 ID 找到對應的 SQL 語句。
? 步驟 3:執行 SQL 并返回結果 代理對象通過 SqlSession
調用底層方法(如 selectOne
、selectList
),執行 SQL 并將結果映射為 Java 對象。
3. 關鍵設計優勢
? 解耦接口與實現 開發者只需定義接口和 SQL 映射,MyBatis 自動生成代理對象,避免手動編寫模板代碼。
? 靈活性與可維護性 SQL 與 Java 代碼分離,修改 SQL 無需重新編譯代碼,同時支持動態 SQL 和復雜映射。
? 性能優化 代理對象通過緩存 MappedStatement
(包含 SQL、參數、結果映射等信息)提升執行效率。
4. 話術
-
MapperProxy
的invoke
方法 代理對象調用方法時,會進入MapperProxy.invoke
,通過MapperMethod
封裝 SQL 執行邏輯。(封裝?還是映射?) -
Configuration
類的核心作用 在 MyBatis 啟動時,Configuration
類會加載所有 Mapper 接口和 XML 文件,建立接口方法與 SQL 的映射關系。