Mybatis 與 Springboot 集成過程詳解
- 一. 核心概念與優勢
- 二.Mybatis 核心類簡介
- 1.MybatisAutoConfiguration
- 2.MapperScans
- 3.MapperScannerRegistrar
- 4.MapperFactoryBean
- 5.Configuration
- 6.MapperRegistry
- 7.MapperProxy 與 MapperProxyFactory
- 7.1核心定位與職責
- 7.22. ??MapperProxy(動態代理處理器)??
- 7.3 協作流程與執行機制
- 三.參考圖
一. 核心概念與優勢
在開始之前,先快速了解為什么這種集成如此流行:
-
MyBatis??: 一個優秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。它避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
-
Spring Boot??: 旨在簡化 Spring 應用的初始搭建和開發過程,提供了大量的自動配置。
-
集成優勢??:
-
??簡化配置??: Spring Boot 為 MyBatis 提供了官方 starter,極大減少了 XML 配置。
-
??自動裝配??: 自動配置 SqlSessionFactory、SqlSessionTemplate、DataSource等 bean。
-
??無縫整合??: 與 Spring 的事務管理、AOP 等特性完美結合
-
二.Mybatis 核心類簡介
1.MybatisAutoConfiguration
MybatisAutoConfiguration 是 MyBatis Spring Boot Starter 的核心自動配置類,通過 META-INF/spring.factories文件注冊到 Spring 容器中。當應用啟動時,@EnableAutoConfiguration會觸發其加載,前提是滿足以下條件:
-
類路徑存在 SqlSessionFactory和 SqlSessionFactoryBean(確保 MyBatis 核心依賴已引入)。
-
容器中存在??唯一的數據源 Bean??(依賴 DataSourceAutoConfiguration完成數據源配置)。
-
在數據源配置完成后執行(通過 @AutoConfigureAfter(DataSourceAutoConfiguration.class)控制加載順序)
2.MapperScans
基本功能與作用
.
1.批量掃描注冊
-
自動掃描指定包路徑下的 Mapper 接口,生成 BeanDefinition并注冊到 Spring 容器。
-
避免在每個 Mapper 接口上單獨添加 @Mapper注解,簡化配置。
2.支持多路徑與通配符
-
支持數組形式指定多個包路徑(如 @MapperScan({“com.dao.user”, “com.dao.product”}))。
-
支持通配符匹配(如 com.example.*.mapper掃描一級子包,com.example.**.mapper掃描多級子包)。
3.多數據源適配
- 結合 sqlSessionFactoryRef或 sqlSessionTemplateRef屬性,為不同數據源指定獨立的 SQL 會話工廠或模板
核心屬性解析
屬性名 | 功能說明 | 示例 |
---|---|---|
value/ basePackages | 指定掃描的包路徑(支持數組) | @MapperScan(“com.dao”) |
basePackageClasses | 通過類的包路徑定位掃描范圍(類型安全) | @MapperScan(basePackageClasses=UserMapper.class) |
annotationClass | 僅掃描帶有指定注解的接口(默認掃描所有接口) | annotationClass = Repository.class |
markerInterface | 僅掃描繼承指定父接口的接口 | markerInterface = BaseMapper.class |
sqlSessionFactoryRef | 指定多數據源下使用的 SqlSessionFactoryBean 名稱 | sqlSessionFactoryRef = “ds1SqlSessionFactory” |
factoryBean | 自定義 MapperFactoryBean實現類(需繼承 MapperFactoryBean) | factoryBean = CustomMapperFactoryBean.class |
3.MapperScannerRegistrar
核心定位與作用
1.注解解析樞紐
@MapperScan注解通過 @Import(MapperScannerRegistrar.class)引入該類,使其成為 Spring 容器啟動時處理 Mapper 掃描配置的入口點。
2.動態注冊引擎
實現 ImportBeanDefinitionRegistrar接口,在 Spring 容器初始化階段動態注冊 MapperScannerConfigurer的 BeanDefinition,從而將用戶配置(如包路徑、過濾條件)轉化為 Spring 可執行的掃描任務。
3.多數據源適配橋梁
支持通過 sqlSessionFactoryRef或 sqlSessionTemplateRef屬性關聯特定數據源,解決多數據源場景下 Mapper 與 SQL 會話工廠的綁定問題
核心實現機制
- 注解屬性解析
- 讀取 @MapperScan中的 basePackages、basePackageClasses等屬性,構建待掃描的包路徑列表。
- 解析過濾條件(如 annotationClass、markerInterface),定制掃描范圍。
- ClassPathMapperScanner 初始化
創建 ClassPathMapperScanner對象(繼承自 Spring 的 ClassPathBeanDefinitionScanner),并配置其屬性:
- 設置資源加載器(ResourceLoader)
- 注入自定義的 Bean 名稱生成器(BeanNameGenerator)
- 定 Mapper 代理工廠類(MapperFactoryBean)。
- 接口掃描與代理轉換
調用 scanner.doScan()方法掃描目標包路徑,通過重寫 isCandidateComponent()確保僅掃描接口類型:掃描完成后,將接口的 BeanDefinition 替換為 MapperFactoryBean類型,并注入構造參數(原接口類名),為后續動態代理奠基
- ClassPathMapperScanner
- 應用啟動時,實際注入到服務層的Mapper接口,就是這個轉換后的代理類實例
4.MapperFactoryBean
MapperFactoryBean→ SqlSessionDaoSupport→ DaoSupport
MapperFactoryBean 是 MyBatis-Spring 整合的核心組件,負責將 MyBatis 的 Mapper 接口動態代理并注冊為 Spring 容器中的 Bean,從而簡化數據訪問層的開發。其設計基于 Spring 的 FactoryBean接口,實現了接口代理與資源管理的自動化
1.??動態代理生成??
MapperFactoryBean 通過 JDK 動態代理技術,為 Mapper 接口創建代理對象。當調用接口方法時,代理對象將請求轉發給 MyBatis 的 SqlSession,執行對應的 SQL 操作。??無需手動編寫實現類??,顯著減少冗余代碼
2.資源生命周期管理??
自動管理 SqlSession的開啟、關閉及事務控制:
- 會話綁定??:確保每次操作在正確的 SqlSession中執行。
- ??事務集成??:與 Spring 事務管理器協同,支持聲明式事務(如 @Transactional)。
3.異常轉換??
將 MyBatis 的 PersistenceException轉換為 Spring 的 DataAccessException體系,統一異常處理
MapperFactoryBean 是 MyBatis-Spring 整合的??動態代理樞紐??,通過三大核心能力簡化開發:
- 自動化代理生成??:消除 DAO 實現類,直接操作接口。
- 資源管理集成??:無縫管理 SqlSession生命周期與 Spring 事務。
- 靈活配置擴展??:支持 XML 顯式聲明或注解批量掃描,適配單數據源與多數據源場景
5.Configuration
全類名:org.apache.ibatis.session.Configuration
1.全局配置容器
Configuration對象在 MyBatis 初始化時創建(通常通過解析 mybatis-config.xml或 Java API 構建),集中存儲以下配置:
- 環境信息():包含數據源(DataSource)和事務管理器(TransactionFactory),支撐數據庫連接與事務控制。
- 全局設置():如 cacheEnabled(二級緩存開關)、lazyLoadingEnabled(延遲加載)、mapUnderscoreToCamelCase(下劃線轉駝峰)等運行時行為開關。
- 注冊中心:管理類型別名(TypeAliasRegistry)、類型處理器(TypeHandlerRegistry)、插件(InterceptorChain)等擴展點。
2.SQL 語句管理中心
維護關鍵映射組件的注冊表,以 Map結構存儲:
- mappedStatements:管理所有 SQL 操作(Select/Insert/Update/Delete),Key 為 SQL 語句 ID(如 “com.example.UserMapper.selectById”)。
- resultMaps:存儲結果集映射規則()。
- caches:管理命名空間級別的二級緩存。
3.核心組件工廠
提供方法創建 MyBatis 執行鏈的關鍵對象:
- newExecutor():生成 Executor(SQL 執行器),支持 SIMPLE、REUSE、BATCH三種模式。
- newStatementHandler():創建 StatementHandler(處理 JDBC Statement)。
- newParameterHandler()/ newResultSetHandler():處理參數綁定與結果集映射
Configuration作為 MyBatis 的??配置中樞與運行時引擎??,通過三大核心能力支撐框架運作:
1.統一配置管理??:整合 XML/注解/Javaconfig 配置源,提供全局訪問接口。
2.組件調度工廠??:動態創建 Executor、StatementHandler等核心執行鏈對象。
3.??擴展性基石??:通過攔截器鏈(InterceptorChain)和類型處理器(TypeHandlerRegistry)支持深度定制
6.MapperRegistry
MapperRegistry是 MyBatis 框架中??管理 Mapper 接口注冊與代理對象生成的核心組件??,作為 MyBatis 配置中樞 Configuration的一部分,它在框架啟動時初始化,并在運行時支撐面向接口的數據庫操作模式。
核心作用與定位??
1.??Mapper 接口的注冊中心??
MapperRegistry集中管理所有需被 MyBatis 識別的 Mapper 接口,確保接口與 SQL 映射的關聯。它通過內部維護的映射表 knownMappers(類型為 Map<Class<?>, MapperProxyFactory<?>>)實現:
??Key??:Mapper 接口的 Class對象(如 UserMapper.class)。
??Value??:為該接口創建的代理工廠 MapperProxyFactory,用于生成動態代理對象。
2.??動態代理對象的提供者??
當調用 sqlSession.getMapper(UserMapper.class)時,SqlSession委托 MapperRegistry查找接口對應的 MapperProxyFactory,并生成代理對象。此代理對象攔截接口方法調用,將其轉化為 SQL 執行邏輯。
3.??接口與 SQL 映射的綁定樞紐??
在注冊階段,MapperRegistry觸發注解或 XML 的解析(通過 MapperAnnotationBuilder),將接口方法關聯到具體的 SQL 語句(MappedStatement),實現??方法調用 → SQL 執行??的動態綁定
MapperRegistry是 MyBatis ??面向接口編程的基石??,通過三層次協作實現高效數據訪問:
1.??注冊層??:統一管理 Mapper 接口,關聯代理工廠。
2.??代理層??:動態生成代理對象,攔截方法調用。
3.執行層??:將方法調用路由至 SqlSession,執行具體 SQL
7.MapperProxy 與 MapperProxyFactory
MapperProxy 與 MapperProxyFactory 是 MyBatis 實現 ??Mapper 接口動態代理??的核心組件,二者協同完成接口方法與 SQL 語句的綁定,使開發者無需編寫實現類即可操作數據庫
7.1核心定位與職責
- ??MapperProxyFactory(代理對象工廠)??
- ??職責??:
負責生產 Mapper 接口的代理對象實例(MapperProxy)。每個 Mapper 接口對應一個獨立的 MapperProxyFactory實例。 - ??關鍵屬性??:
- mapperInterface:需代理的 Mapper 接口 Class 對象(如 UserMapper.class)
- methodCache:緩存接口方法與 MapperMethod的映射,避免重復解析
7.22. ??MapperProxy(動態代理處理器)??
- 職責??:
實現 InvocationHandler接口,攔截 Mapper 接口方法調用,將其轉換為底層 SQL 執行邏輯。 - ??關鍵依賴??:
- SqlSession:執行 SQL 的會話對象。
- methodCache:緩存方法對應的 MapperMethod,優化性能。
- ??代理控制邏輯??:
- ??Object 原生方法??(如 toString):直接調用原生實現。
- 接口默認方法??:調用默認方法實現。
- ??抽象方法??:委托給 MapperMethod執行 SQL
7.3 協作流程與執行機制
代理對象生成流程
1.注冊階段:
MyBatis 啟動時通過 MapperRegistry掃描并注冊所有 Mapper 接口,為每個接口創建 MapperProxyFactory實例。
2.調用階段:
用戶調用 sqlSession.getMapper(UserMapper.class):
- MapperRegistry查找接口對應的 MapperProxyFactory。
- MapperProxyFactory生成代理對象(內部創建 MapperProxy并綁定至接口)。
- 方法攔截與 SQL 執行
當調用代理對象的接口方法(如 userMapper.selectById(1)):
1.方法攔截:
MapperProxy.invoke()攔截調用,跳過非抽象方法(如 Object方法)。
2.方法映射:
通過 cachedMapperMethod()獲取或創建 MapperMethod對象(封裝 SQL 語句、參數映射、返回類型)。
3.SQL 執行:
MapperMethod.execute()根據操作類型(SELECT/UPDATE)調用 SqlSession的對應方法(如 selectOne()),并返回結果
總結
- MapperProxyFactory?? 是代理對象的??生產引擎??,通過工廠模式屏蔽動態代理的復雜性。
- ??MapperProxy?? 是代理邏輯的??執行樞紐??,將接口方法調用轉化為 SQL 會話操作,實現 ORM 的“接口即實現”范式
- ??協同價值??:二者通過動態代理機制,徹底解耦接口定義與 SQL 執行,成為 MyBatis 簡化 DAO 層開發的核心設計,也是其區別于傳統 ORM 框架的標志性特性