理解 MyBatis 是如何在 Spring 容器中初始化的
MyBatis 初始化過程就是生成一些必須的物件放到 Spring 容器中。問題是這個過程到底生成了哪些物件?當遇到 MyBatis 初始化失敗時,如何正確的找到分析問題的切入點?本文將針對這些問題進行介紹。
本文基於 MyBatis 3和 Spring,假設讀者已經知道如何使用 Maven 和 MyBatis,以及瞭解 Spring 的容器機制。
一、Mybatis 三件套
我們知道 MyBatis 的主要功能是由 SqlSessionFactory 和 Mapper 兩者提供的,初始化 MyBatis 就是初始化這兩類物件。除此之外 DataSource 作為資料庫訪問物件也是必不可少。因此首先我們應該記住 MyBatis 初始化的核心三件套:
DataSource
:它是訪問資料庫所必須的資料來源物件,這個初始化失敗就無法直接訪問資料庫。SqlSessionFactoryBean
:這是在 Spring 容器中對 SqlSessionFactory 初始化過程的封裝。MapperScannerConfigurer
:這是在 Spring 容器中對 Mapper 初始化過程的封裝。
具體來說,一個簡單的初始化過程就是下面這樣:
@Configuration
public class SpringMyBatisApplication {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(SpringMyBatisApplication.class);
}
@Bean
public DataSource dataSource() {
return ...;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
return ...;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
return ...;
}
}
接下來介紹三件套各自如何初始化,下面的內容是可以實際操作的,不妨動手試試。
1. DataSource 初始化
首先我們建立一個空的 Maven 專案,在 pom.xml 中加入下面的依賴關係:
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- 資料庫 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
本文重在演示 MyBatis 的初始化過程,所以沒有複雜的 SQL,資料庫用的是嵌入式資料庫 h2。
然後我們在 com.hyd.mybatis3test
包下面建立一個 SpringMyBatisApplication
類,程式碼在前面給過了。
對應的 DataSource 初始化實現如下:
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:test");
return dataSource;
}
2. SqlSessionFactoryBean 初始化
SqlSessionFactoryBean 是對 SqlSessionFactory 初始化過程的封裝,Spring 會在適當的時候執行這個初始化過程,得到最終的 SqlSessionFactory 物件。
SqlSessionFactoryBean 的建立過程如下(注意方法簽名在前面的基礎上有變動):
@Bean
public SqlSessionFactoryBean sqlSessionFactory(
DataSource dataSource,
ResourcePatternResolver resolver
) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(resolver.getResources("classpath*:mappers/*.xml"));
return bean;
}
其中:
- 第一個引數 dataSource 就是前面生成的資料來源物件;
- 第二個引數 resolver 是 Spring 自動提供的,用於搜尋指定路徑下的所有 xml 檔案。本文不會包含 xml 檔案,所以這個配置是無效的,這行可以不寫,不過寫了也不影響程式執行。
3. MapperScannerConfigurer 初始化
MapperScannerConfigurer 的職責是在指定路徑下搜尋所有的 Mapper 介面類(參考它的 postProcessBeanDefinitionRegistry()
方法),並通過 MapperFactoryBean 將其註冊到 MapperRegistry 中。
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.hyd.mybatis3test");
return configurer;
}
4. 驗證初始化過程成功
為了驗證上面的初始化過程完成了,我們在 com.hyd.mybatis3test
包下面建立一個 Mapper 類:
@Mapper
public interface SampleMapper {
@Update("create table if not exists user(id int)")
void createUserTable();
}
以及一個 Service 類:
@Service
public static class SampleService {
@Autowired
private SampleMapper sampleMapper;
@PostConstruct
public void init() {
sampleMapper.createUserTable();
}
}
然後別忘了在 SpringMyBatisApplication 頂上新增一個 @ComponentScan("com.hyd.mybatis3test")
註解,否則 Spring 會找不到 SampleService。
執行 SpringMyBatisApplication.main() 方法,我們就能在輸出中找到這樣的內容:
...
SampleMapper.createUserTable - ==> Preparing: create table if not exists user(id int)
SampleMapper.createUserTable - ==> Parameters:
SampleMapper.createUserTable - <== Updates: 0
...
這說明這條建立表格的 SQL 語句成功執行了。
在前面三件套的基礎上,MyBatis 也提供了更多的封裝。有了本文上面的鋪墊,相信讀者對這些封裝方式理解起來也會輕鬆很多。
二、@MapperScan 註解
@MapperScan 註解只不過是 MapperScannerConfigurer 的啟動器而已,使用這個註解,可以代替前面的 MapperScannerConfigurer 初始化。
三、SpringBoot 自動初始化
MyBatis 提供 mybatis-spring-boot-starter 庫用於在 Spring Boot 專案中自動初始化:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
這個所謂的自動初始化實際上就是初始化 SqlSessionFactory
物件。初始化的過程由 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
完成,所需的配置都從 “mybatis-” 字首的配置屬性中獲取,具體可以參考 org.mybatis.spring.boot.autoconfigure.MybatisProperties
類。
總結
總之,MyBatis 的初始化核心過程就是三件套的初始化。而在 Spring Boot 應用中,結合自動初始化和 @MapperScan 註解,我們無需手工初始化上這三件套,就能直接從容器中得到 Mapper 物件。
相關文章
- MyBatis是如何初始化的?MyBatis
- 從原始碼看Spring中IOC容器的實現(二):IOC容器的初始化原始碼Spring
- Mybatis的初始化和結合Spring Framework後初始化的MyBatisSpringFramework
- spring ioc原理-容器初始化的大致流程Spring
- WEB應用是如何運用Spring的?#①Spring的IOC容器如何在WEB中建立?WebSpring
- Spring原始碼分析:Spring IOC容器初始化Spring原始碼
- 如何在mybatis 中傳多個引數,如何在mybatis 中遍歷 集合?MyBatis
- 深入理解Spring IOC容器Spring
- Mybatis的初始化和結合Spring Framework後初始化的原始碼探究MyBatisSpringFramework原始碼
- Spring容器 —— 深入 bean 的載入(五、初始化 bean)SpringBean
- Spring MVC 原始碼解析(二)— 容器初始化SpringMVC原始碼
- 深入原始碼理解Spring整合MyBatis原理原始碼SpringMyBatis
- Mybatis在Spring中的使用(三)MyBatisSpring
- Spring IoC容器初始化 — Resource定位原始碼分析Spring原始碼
- 【spring原始碼學習】spring的IOC容器在初始化bean過程Spring原始碼Bean
- 深入理解spring容器中的控制反轉(IOC)和依賴注入(DI)Spring依賴注入
- Spring Boot + Mybatis + Spring MVC環境配置(一) :Spring Boot初始化,依賴新增Spring BootMyBatisMVC
- 精盡Spring MVC原始碼分析 - WebApplicationContext 容器的初始化SpringMVC原始碼WebAPPContext
- 兩個案例輕鬆理解MyBatis中的TypeHandler!MyBatis
- 如何在Docker容器中執行GUI程式DockerGUI
- 深入理解Spring系列之六:bean初始化SpringBean
- Spring_Mybatis整合 註解配置類與xml配置檔案兩種方式分析及初始化IOC容器與監聽獲取取IOC容器SpringMyBatisXML
- spring-IOC容器原始碼分析(一)bean初始化流程Spring原始碼Bean
- Spring Boot 2.2中的延遲初始化Spring Boot
- 深入理解Spring IOC容器及擴充套件Spring套件
- MyBatis-08-Spring的MyBatis InterceptorMyBatisSpring
- 從Spring中學到的【2】--容器類Spring
- Spring框架中的容器以及兩大特性Spring框架
- Spring中Bean及@Bean的理解SpringBean
- 在Linux中,如何理解加密工具?如GnuPG和OpenSSL。Linux加密
- 精盡MyBatis原始碼分析 - MyBatis初始化(三)之 SQL 初始化(上)MyBatis原始碼SQL
- 精盡MyBatis原始碼分析 - MyBatis初始化(四)之 SQL 初始化(下)MyBatis原始碼SQL
- spring 整合 mybatis 及mybatis 的 crud 操作SpringMyBatis
- spring:spring與mybatis的整合SpringMyBatis
- 如何理解Spring中的IOC和AOPSpring
- Spring的IOC容器Spring
- Spring 的容器配置Spring
- Spring Boot中初始化資源的幾種方式Spring Boot