理解 MyBatis 是如何在 Spring 容器中初始化的
MyBatis 初始化過(guò)程就是生成一些必須的對(duì)象放到 Spring 容器中。問(wèn)題是這個(gè)過(guò)程到底生成了哪些對(duì)象?當(dāng)遇到 MyBatis 初始化失敗時(shí),如何正確的找到分析問(wèn)題的切入點(diǎn)?本文將針對(duì)這些問(wèn)題進(jìn)行介紹。
本文基于 MyBatis 3 和 Spring,假設(shè)讀者已經(jīng)知道如何使用 Maven 和 MyBatis,以及了解 Spring 的容器機(jī)制。
一、Mybatis 三件套
我們知道 MyBatis 的主要功能是由 SqlSessionFactory 和 Mapper 兩者提供的,初始化 MyBatis 就是初始化這兩類對(duì)象。除此之外 DataSource 作為數(shù)據(jù)庫(kù)訪問(wèn)對(duì)象也是必不可少。因此首先我們應(yīng)該記住 MyBatis 初始化的核心三件套:
DataSource:它是訪問(wèn)數(shù)據(jù)庫(kù)所必須的數(shù)據(jù)源對(duì)象,這個(gè)初始化失敗就無(wú)法直接訪問(wèn)數(shù)據(jù)庫(kù)。 SqlSessionFactoryBean:這是在 Spring 容器中對(duì) SqlSessionFactory 初始化過(guò)程的封裝。 MapperScannerConfigurer:這是在 Spring 容器中對(duì) Mapper 初始化過(guò)程的封裝。具體來(lái)說(shuō),一個(gè)簡(jiǎn)單的初始化過(guò)程就是下面這樣:
@Configurationpublic 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 ...; }}
接下來(lái)介紹三件套各自如何初始化,下面的內(nèi)容是可以實(shí)際操作的,不妨動(dòng)手試試。
1. DataSource 初始化
首先我們創(chuàng)建一個(gè)空的 Maven 項(xiàng)目,在 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ù)庫(kù) --><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 的初始化過(guò)程,所以沒有復(fù)雜的 SQL,數(shù)據(jù)庫(kù)用的是嵌入式數(shù)據(jù)庫(kù) h2。
然后我們?cè)?com.hyd.mybatis3test 包下面創(chuàng)建一個(gè) SpringMyBatisApplication 類,代碼在前面給過(guò)了。
對(duì)應(yīng)的 DataSource 初始化實(shí)現(xiàn)如下:
@Beanpublic DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName('org.h2.Driver'); dataSource.setUrl('jdbc:h2:mem:test'); return dataSource;}
2. SqlSessionFactoryBean 初始化
SqlSessionFactoryBean 是對(duì) SqlSessionFactory 初始化過(guò)程的封裝,Spring 會(huì)在適當(dāng)?shù)臅r(shí)候執(zhí)行這個(gè)初始化過(guò)程,得到最終的 SqlSessionFactory 對(duì)象。
SqlSessionFactoryBean 的創(chuàng)建過(guò)程如下(注意方法簽名在前面的基礎(chǔ)上有變動(dòng)):
@Beanpublic SqlSessionFactoryBean sqlSessionFactory( DataSource dataSource, ResourcePatternResolver resolver) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(resolver.getResources('classpath*:mappers/*.xml')); return bean;}
其中:
第一個(gè)參數(shù) dataSource 就是前面生成的數(shù)據(jù)源對(duì)象; 第二個(gè)參數(shù) resolver 是 Spring 自動(dòng)提供的,用于搜索指定路徑下的所有 xml 文件。本文不會(huì)包含 xml 文件,所以這個(gè)配置是無(wú)效的,這行可以不寫,不過(guò)寫了也不影響程序運(yùn)行。3. MapperScannerConfigurer 初始化
MapperScannerConfigurer 的職責(zé)是在指定路徑下搜索所有的 Mapper 接口類(參考它的 postProcessBeanDefinitionRegistry() 方法),并通過(guò) MapperFactoryBean 將其注冊(cè)到 MapperRegistry 中。
@Beanpublic MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setBasePackage('com.hyd.mybatis3test'); return configurer;}
4. 驗(yàn)證初始化過(guò)程成功
為了驗(yàn)證上面的初始化過(guò)程完成了,我們?cè)?com.hyd.mybatis3test 包下面創(chuàng)建一個(gè) Mapper 類:
@Mapperpublic interface SampleMapper { @Update('create table if not exists user(id int)') void createUserTable();}
以及一個(gè) Service 類:
@Servicepublic static class SampleService { @Autowired private SampleMapper sampleMapper; @PostConstruct public void init() { sampleMapper.createUserTable(); }}
然后別忘了在 SpringMyBatisApplication 頂上添加一個(gè) @ComponentScan('com.hyd.mybatis3test') 注解,否則 Spring 會(huì)找不到 SampleService。
運(yùn)行 SpringMyBatisApplication.main() 方法,我們就能在輸出中找到這樣的內(nèi)容:
...SampleMapper.createUserTable - ==> Preparing: create table if not exists user(id int)SampleMapper.createUserTable - ==> Parameters:SampleMapper.createUserTable - <== Updates: 0...
這說(shuō)明這條創(chuàng)建表格的 SQL 語(yǔ)句成功執(zhí)行了。
在前面三件套的基礎(chǔ)上,MyBatis 也提供了更多的封裝。有了本文上面的鋪墊,相信讀者對(duì)這些封裝方式理解起來(lái)也會(huì)輕松很多。
二、@MapperScan 注解
@MapperScan 注解只不過(guò)是 MapperScannerConfigurer 的啟動(dòng)器而已,使用這個(gè)注解,可以代替前面的 MapperScannerConfigurer 初始化。
三、SpringBoot 自動(dòng)初始化
MyBatis 提供 mybatis-spring-boot-starter 庫(kù)用于在 Spring Boot 項(xiàng)目中自動(dòng)初始化:
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version></dependency>
這個(gè)所謂的自動(dòng)初始化實(shí)際上就是初始化 SqlSessionFactory 對(duì)象。初始化的過(guò)程由 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 完成,所需的配置都從 'mybatis-' 前綴的配置屬性中獲取,具體可以參考 org.mybatis.spring.boot.autoconfigure.MybatisProperties 類。
總結(jié)
總之,MyBatis 的初始化核心過(guò)程就是三件套的初始化。而在 Spring Boot 應(yīng)用中,結(jié)合自動(dòng)初始化和 @MapperScan 注解,我們無(wú)需手工初始化上這三件套,就能直接從容器中得到 Mapper 對(duì)象。
到此這篇關(guān)于理解 MyBatis 是如何在 Spring 容器中初始化的的文章就介紹到這了,更多相關(guān)mybatis在spring中的初始化內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. IntelliJ IDEA導(dǎo)出項(xiàng)目的方法2. IntelliJ IDEA設(shè)置自動(dòng)提示功能快捷鍵的方法3. IntelliJ IDEA設(shè)置編碼格式的方法4. Ajax對(duì)xml信息的接收和處理操作實(shí)例分析5. WML開發(fā)教程之 WAP網(wǎng)站服務(wù)器配置方法6. 用XML和XSL來(lái)生成動(dòng)態(tài)頁(yè)面7. Ajax報(bào)錯(cuò)400的參考解決辦法8. 谷歌Chrome瀏覽器開發(fā)者工具教程—JS調(diào)試篇9. Ajax實(shí)現(xiàn)頁(yè)面無(wú)刷新留言效果10. JS實(shí)現(xiàn)炫酷雪花飄落效果
