共計(jì) 3586 個(gè)字符,預(yù)計(jì)需要花費(fèi) 9 分鐘才能閱讀完成。
這篇文章將為大家詳細(xì)講解有關(guān) Spring 與 Mybatis 整合的 MapperScannerConfigurer 怎么用,丸趣 TV 小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
MapperScannerConfigurer 介紹
MapperScannerConfigurer 是 spring 和 mybatis 整合的 mybatis-spring jar 包中提供的一個(gè)類。
想要了解該類的作用,就得先了解 MapperFactoryBean。
MapperFactoryBean 的出現(xiàn)為了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 編寫數(shù)據(jù)訪問對(duì)象 (DAO) 的代碼, 使用動(dòng)態(tài)代理實(shí)現(xiàn)。
比如下面這個(gè)官方文檔中的配置:
bean id= userMapper >org.mybatis.spring.sample.mapper.UserMapper 是一個(gè)接口,我們創(chuàng)建一個(gè) MapperFactoryBean 實(shí)例,然后注入這個(gè)接口和 sqlSessionFactory(mybatis 中提供的 SqlSessionFactory 接口,MapperFactoryBean 會(huì)使用 SqlSessionFactory 創(chuàng)建 SqlSession)這兩個(gè)屬性。
之后想使用這個(gè) UserMapper 接口的話,直接通過 spring 注入這個(gè) bean,然后就可以直接使用了,spring 內(nèi)部會(huì)創(chuàng)建一個(gè)這個(gè)接口的動(dòng)態(tài)代理。
當(dāng)發(fā)現(xiàn)要使用多個(gè) MapperFactoryBean 的時(shí)候,一個(gè)一個(gè)定義肯定非常麻煩,于是 mybatis-spring 提供了 MapperScannerConfigurer 這個(gè)類,它將會(huì)查找類路徑下的映射器并自動(dòng)將它們創(chuàng)建成 MapperFactoryBean。
bean >這段配置會(huì)掃描 org.mybatis.spring.sample.mapper 下的所有接口,然后創(chuàng)建各自接口的動(dòng)態(tài)代理類。
MapperScannerConfigurer 底層代碼分析 以以下代碼為示例進(jìn)行講解(部分代碼,其他代碼及配置省略):
package org.format.dynamicproxy.mybatis.dao;
public interface UserDao { public User getById(int id);
public int add(User user);
public int update(User user);
public int delete(User user);
public List User getAll();
bean >我們先通過測試用例 debug 查看 userDao 的實(shí)現(xiàn)類到底是什么。
我們可以看到,userDao 是 1 個(gè) MapperProxy 類的實(shí)例。
看下 MapperProxy 的源碼,沒錯(cuò),實(shí)現(xiàn)了 InvocationHandler,說明使用了 jdk 自帶的動(dòng)態(tài)代理。
public class MapperProxy T implements InvocationHandler, Serializable {
private static final long serialversionUID = -6424540398559729838L;
private final SqlSession sqlSession;
private final Class T mapperinterface;
private final Map Method, MapperMethod methodCache;
public MapperProxy(SqlSession sqlSession, Class T mapperInterface, Map Method, MapperMethod methodCache) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
this.methodCache = methodCache;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) {
try { return method.invoke(this, args);
} catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t);
}
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
private MapperMethod cachedMapperMethod(Method method) { MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) { mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
}
下面開始分析 MapperScannerConfigurer 的源碼
MapperScannerConfigurer 實(shí)現(xiàn)了 BeanDefinitionRegistryPostProcessor 接口,BeanDefinitionRegistryPostProcessor 接口是一個(gè)可以修改 spring 工長中已定義的 bean 的接口,該接口有個(gè) postProcessBeanDefinitionRegistry 方法。
然后我們看下 ClassPathMapperScanner 中的關(guān)鍵是如何掃描對(duì)應(yīng) package 下的接口的。
其實(shí) MapperScannerConfigurer 的作用也就是將對(duì)應(yīng)的接口的類型改造為 MapperFactoryBean,而這個(gè) MapperFactoryBean 的屬性 mapperInterface 是原類型。MapperFactoryBean 本文開頭已分析過。
所以最終我們還是要分析 MapperFactoryBean 的實(shí)現(xiàn)原理!
MapperFactoryBean 繼承了 SqlSessionDaoSupport 類,SqlSessionDaoSupport 類繼承 DaoSupport 抽象類,DaoSupport 抽象類實(shí)現(xiàn)了 InitializingBean 接口,因此實(shí)例個(gè) MapperFactoryBean 的時(shí)候,都會(huì)調(diào)用 InitializingBean 接口的 afterPropertiesSet 方法。
DaoSupport 的 afterPropertiesSet 方法:
MapperFactoryBean 重寫了 checkDaoConfig 方法:
然后通過 spring 工廠拿對(duì)應(yīng)的 bean 的時(shí)候:
這里的 SqlSession 是 SqlSessionTemplate,SqlSessionTemplate 的 getMapper 方法:
Configuration 的 getMapper 方法,會(huì)使用 MapperRegistry 的 getMapper 方法:
MapperRegistry 的 getMapper 方法:
MapperProxyFactory 構(gòu)造 MapperProxy:
沒錯(cuò)!MapperProxyFactory 就是使用了 jdk 組帶的 Proxy 完成動(dòng)態(tài)代理。
MapperProxy 本來一開始已經(jīng)提到。MapperProxy 內(nèi)部使用了 MapperMethod 類完成方法的調(diào)用:
下面,我們以 UserDao 的 getById 方法來 debug 看看 MapperMethod 的 execute 方法是如何走的。
@Test
public void testGet() { int id = 1; system.out.println(userDao.getById(id));
select id= getById

關(guān)于“Spring 與 Mybatis 整合的 MapperScannerConfigurer 怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。