理解 MyBatis 是如何在 Spring 容器中初始化的
MyBatis 初始化過程就是生成一些必須的對象放到 Spring 容器中。問題是這個過程到底生成了哪些對象?當(dāng)遇到 MyBatis 初始化失敗時,如何正確的找到分析問題的切入點?本文將針對這些問題進(jìn)行介紹。
本文基于 MyBatis 3 和 Spring,假設(shè)讀者已經(jīng)知道如何使用 Maven 和 MyBatis,以及了解 Spring 的容器機制。
一、Mybatis 三件套
我們知道 MyBatis 的主要功能是由 SqlSessionFactory 和 Mapper 兩者提供的,初始化 MyBatis 就是初始化這兩類對象。除此之外 DataSource 作為數(shù)據(jù)庫訪問對象也是必不可少。因此首先我們應(yīng)該記住 MyBatis 初始化的核心三件套:
- DataSource:它是訪問數(shù)據(jù)庫所必須的數(shù)據(jù)源對象,這個初始化失敗就無法直接訪問數(shù)據(jù)庫。
- 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 ...;
}
}
接下來介紹三件套各自如何初始化,下面的內(nèi)容是可以實際操作的,不妨動手試試。
1. DataSource 初始化
首先我們創(chuàng)建一個空的 Maven 項目,在 pom.xml 中加入下面的依賴關(guān)系:
<!-- 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> <!-- 數(shù)據(jù)庫 --> <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 的初始化過程,所以沒有復(fù)雜的 SQL,數(shù)據(jù)庫用的是嵌入式數(shù)據(jù)庫 h2。
然后我們在 com.hyd.mybatis3test 包下面創(chuàng)建一個 SpringMyBatisApplication 類,代碼在前面給過了。
對應(yīng)的 DataSource 初始化實現(xiàn)如下:
@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 會在適當(dāng)?shù)臅r候執(zhí)行這個初始化過程,得到最終的 SqlSessionFactory 對象。
SqlSessionFactoryBean 的創(chuàng)建過程如下(注意方法簽名在前面的基礎(chǔ)上有變動):
@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;
}
其中:
- 第一個參數(shù) dataSource 就是前面生成的數(shù)據(jù)源對象;
- 第二個參數(shù) resolver 是 Spring 自動提供的,用于搜索指定路徑下的所有 xml 文件。本文不會包含 xml 文件,所以這個配置是無效的,這行可以不寫,不過寫了也不影響程序運行。
3. MapperScannerConfigurer 初始化
MapperScannerConfigurer 的職責(zé)是在指定路徑下搜索所有的 Mapper 接口類(參考它的 postProcessBeanDefinitionRegistry() 方法),并通過 MapperFactoryBean 將其注冊到 MapperRegistry 中。
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.hyd.mybatis3test");
return configurer;
}
4. 驗證初始化過程成功
為了驗證上面的初始化過程完成了,我們在 com.hyd.mybatis3test 包下面創(chuàng)建一個 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() 方法,我們就能在輸出中找到這樣的內(nèi)容:
...
SampleMapper.createUserTable - ==> Preparing: create table if not exists user(id int)
SampleMapper.createUserTable - ==> Parameters:
SampleMapper.createUserTable - <== Updates: 0
...
這說明這條創(chuàng)建表格的 SQL 語句成功執(zhí)行了。
在前面三件套的基礎(chǔ)上,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 類。
總結(jié)
總之,MyBatis 的初始化核心過程就是三件套的初始化。而在 Spring Boot 應(yīng)用中,結(jié)合自動初始化和 @MapperScan 注解,我們無需手工初始化上這三件套,就能直接從容器中得到 Mapper 對象。
到此這篇關(guān)于理解 MyBatis 是如何在 Spring 容器中初始化的的文章就介紹到這了,更多相關(guān)mybatis在spring中的初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用 Spring Boot 2.0 + WebFlux 實現(xiàn) RESTful API功能
什么是 Spring WebFlux, 它是一種異步的, 非阻塞的, 支持背壓(Back pressure)機制的Web 開發(fā)框架.下面通過本文給大家介紹使用 Spring Boot 2.0 + WebFlux 實現(xiàn) RESTful API功能,需要的朋友參考下吧2018-01-01
SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞的實現(xiàn)詳解
這篇文章主要介紹了SpringMVC轉(zhuǎn)發(fā)與重定向參數(shù)傳遞,對于重定向,可以通過FlashMap或RedirectAttributes來在請求間傳遞數(shù)據(jù),因為重定向涉及兩個獨立的HTTP請求,而轉(zhuǎn)發(fā)則在同一請求內(nèi)進(jìn)行,數(shù)據(jù)可以直接通過HttpServletRequest共享,需要的朋友可以參考下2022-07-07
Spring?Security中自定義cors配置及原理解析
在Spring框架中,通過自定義CORS配置可根據(jù)實際情況調(diào)整URL的協(xié)議、主機、端口等,以適應(yīng)"同源安全策略",配置原理涉及CorsConfigurer和CorsFilter,自定義配置需要注意@Configuration注解、方法名以及可能的@Autowired注解2024-10-10
Java中InputSteam怎么轉(zhuǎn)String
面了一位實習(xí)生,叫他給我說一下怎么把InputStream轉(zhuǎn)換為String,這種常規(guī)的操作,他竟然都沒有用過我準(zhǔn)備結(jié)合工作經(jīng)驗,整理匯集出了InputStream 到String 轉(zhuǎn)換的十八般武藝,助大家闖蕩 Java 江湖一臂之力,需要的朋友可以參考下2021-06-06
springboot的application.yml配置port不生效的解決方案
這篇文章主要介紹了springboot的application.yml配置port不生效的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07

