国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Spring與Mybatis整合的MapperScannerConfigurer處理過程源碼分析

2019-11-14 21:05:28
字體:
供稿:網(wǎng)友
SPRing與Mybatis整合的MapperScannerConfigurer處理過程源碼分析前言

本文將分析mybatis與spring整合的MapperScannerConfigurer的底層原理,之前已經(jīng)分析過java中實(shí)現(xiàn)動(dòng)態(tài),可以使用jdk自帶api和cglib第三方庫生成動(dòng)態(tài)代理。本文分析的mybatis版本3.2.7,mybatis-spring版本1.2.2。

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" class="org.mybatis.spring.mapper.MapperFactoryBean">  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />  <property name="sqlSessionFactory" ref="sqlSessionFactory" /></bean>

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 class="org.mybatis.spring.mapper.MapperScannerConfigurer">  <property name="basePackage" value="org.mybatis.spring.sample.mapper" /></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 class="org.mybatis.spring.mapper.MapperScannerConfigurer">    <property name="basePackage" value="org.format.dynamicproxy.mybatis.dao"/>    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/></bean>

我們先通過測(cè)試用例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工長(zhǎng)中已定義的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方法是如何走的。

@Testpublic void testGet() {    int id = 1;    System.out.println(userDao.getById(id));}<select id="getById" parameterType="int" resultType="org.format.dynamicproxy.mybatis.bean.User">    SELECT * FROM users WHERE id = #{id}</select>

示例代碼:https://github.com/fangjian0423/dynamic-proxy-mybatis-study

總結(jié)

來到了新公司,接觸了Mybatis,以前接觸過~ 但是接觸的不深入,突然發(fā)現(xiàn)spring與mybatis整合之后可以只寫個(gè)接口而不實(shí)現(xiàn),spring默認(rèn)會(huì)幫我們實(shí)現(xiàn),然后覺得非常神奇,于是寫了篇java動(dòng)態(tài)代碼淺析和本文。

參考資料

https://mybatis.github.io/spring/zh/mappers.html


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 定襄县| 饶河县| 罗定市| 保定市| 邯郸县| 榆中县| 依兰县| 若尔盖县| 信阳市| 余庆县| 抚松县| 丽水市| 东台市| 隆化县| 石台县| 贵溪市| 呼图壁县| 华坪县| 保山市| 屏南县| 井陉县| 临颍县| 化德县| 饶平县| 中方县| 岚皋县| 台北县| 黎城县| 万荣县| 天等县| 丹江口市| 雅江县| 蓬莱市| 吴江市| 五峰| 江西省| 永川市| 成都市| 卓尼县| 尼勒克县| 浮山县|