最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis中SqlSession下的四大對象之執(zhí)行器(executor)

 更新時(shí)間:2019年04月10日 08:44:09   作者:ykzhen2015  
mybatis中sqlsession下的四大對象是指:executor, statementHandler,parameterHandler,resultHandler對象。這篇文章主要介紹了Mybatis中SqlSession下的四大對象之執(zhí)行器(executor),需要的朋友可以參考下

首先我先解釋一下標(biāo)題 四大對象是指:executor, statementHandler,parameterHandler,resultHandler對象。(為了方便下面的文章說道四大對象就專指它們)

它們都是sqlSession的底層類實(shí)現(xiàn),也是插件能夠攔截的四大對象。所以這里已經(jīng)觸及了MyBATIS的底層,動態(tài)代理,反射隨時(shí)可以看到,如果沒有第一篇作為基礎(chǔ),你將十分難以理解它。了解他們的協(xié)作,是插件編寫的基礎(chǔ)之一,所以這是十分的重要。

Executor在sqlSession中的應(yīng)用

上篇我們談到了一個(gè)問題,一個(gè)mapper被執(zhí)行是通過動態(tài)代理來完成的,然后進(jìn)入到了sqlSession的方法中去。這個(gè)并不難理解,但是sqlSession內(nèi)部是怎么運(yùn)行的呢?答案四大對象的協(xié)作。在SqlSession它還是一個(gè)接口,mybatis內(nèi)部是通過DefaultSqlSession這個(gè)實(shí)現(xiàn)類為我們提供服務(wù)的,它比較長,但是我們不需要全部看到,我們只看到很常用的selectList方法便可以了。

package org.apache.ibatis.session.defaults;
public class DefaultSqlSession implements SqlSession {
 private Configuration configuration;
 private Executor executor;
 private boolean autoCommit;
 private boolean dirty;
.......
@Override
 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
  try {
   MappedStatement ms = configuration.getMappedStatement(statement);
   return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
  } catch (Exception e) {
   throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
  } finally {
   ErrorContext.instance().reset();
  }
 }
......
}

我們可以看到它是通過executor去執(zhí)行方法來完成查詢的。

初認(rèn)Executor

那么我們對executor就很感興趣,于是我們看看executor是怎么樣的,首先在MyBATIS中有三種executor:

SimpleExecutor -- SIMPLE 就是普通的執(zhí)行器。

ReuseExecutor -執(zhí)行器會重用預(yù)處理語句(prepared statements)

BatchExecutor --它是批量執(zhí)行器

這些就是mybatis的三種執(zhí)行器。你可以通過配置文件的settings里面的元素defaultExecutorType,配置它,默認(rèn)是采用SimpleExecutor如果你在Spring運(yùn)用它,那么你可以這么配置它:

<bean id="sqlSessionTemplateBatch" class="org.mybatis.spring.SqlSessionTemplate">   
<constructor-arg index="0" ref="sqlSessionFactory" /> 
<!--更新采用批量的executor --> 
<constructor-arg index="1" value="BATCH"/> 
</bean> 

這樣,它便是一個(gè)批量的執(zhí)行器。mybatis的三個(gè)executor都有一個(gè)共同的父類——BaseExecutor。

Executor初始化

首先我們先了解一下mybatis是怎么樣生成executor的。我們看到生成Executor的地方(org.apache.ibatis.session.Configuration):

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
  executorType = executorType == null ? defaultExecutorType : executorType;
  executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
  Executor executor;
  if (ExecutorType.BATCH == executorType) {
   executor = new BatchExecutor(this, transaction);
  } else if (ExecutorType.REUSE == executorType) {
   executor = new ReuseExecutor(this, transaction);
  } else {
   executor = new SimpleExecutor(this, transaction);
  }
  if (cacheEnabled) {
   executor = new CachingExecutor(executor);
  }
  executor = (Executor) interceptorChain.pluginAll(executor);
  return executor;
 }

這里大部分都很好理解,但是有個(gè)地方就好不好理解,它就是:

executor = (Executor) interceptorChain.pluginAll(executor);

這是一段非常重要的代碼,它是采用責(zé)任鏈模式,來產(chǎn)生代理對象。我們需要再深入理解它,打開它具體的pluginAll方法:

public Object pluginAll(Object target) {
  for (Interceptor interceptor : interceptors) {
   target = interceptor.plugin(target);
  }
  return target;
 }

我們這里先介紹一下這段代碼:

Interceptor它是mybatis攔截器必須要實(shí)現(xiàn)的接口,換句話說,這個(gè)遍歷就是遍歷mybatis的攔截器。

然后調(diào)用plugin方法,這個(gè)方法是為了生成代理對象(占位)的。

于是可以想象我們的插件的代理對象將會是一層層的嵌套,所以當(dāng)中任何一個(gè)插件(Interceptor)都有機(jī)會攔截這個(gè)真是的服務(wù)對象(executor),則便是責(zé)任鏈模式,我們完全可以提供插件(Interceptor),進(jìn)入到代理對象的invoke方法里面,來改變executor的行為和方法。

但是我要在這里強(qiáng)調(diào),當(dāng)你使用插件的時(shí)候,你將改變mybatis的executor內(nèi)容實(shí)現(xiàn),你必須慎重的使用它。

如果要我們自己編寫動態(tài)的代理,那么工作量可不小,好在mybatis為我們提供了Plugin.java類來完成我們所需要的功能。

public class Plugin implements InvocationHandler {
 private Object target;
 private Interceptor interceptor;
 private Map<Class<?>, Set<Method>> signatureMap;
 private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
  this.target = target;
  this.interceptor = interceptor;
  this.signatureMap = signatureMap;
 }
 public static Object wrap(Object target, Interceptor interceptor) {
  Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
  Class<?> type = target.getClass();
  Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
  if (interfaces.length > 0) {
   return Proxy.newProxyInstance(
     type.getClassLoader(),
     interfaces,
     new Plugin(target, interceptor, signatureMap));
  }
  return target;
 }
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
   Set<Method> methods = signatureMap.get(method.getDeclaringClass());
   if (methods != null && methods.contains(method)) {
    return interceptor.intercept(new Invocation(target, method, args));
   }
   return method.invoke(target, args);
  } catch (Exception e) {
   throw ExceptionUtil.unwrapThrowable(e);
  }
 }
 ......
}

這里有一個(gè)wrap方法:它會為我們生成代理對象。一旦我們的插件和它綁定,那么我們可以想到就會進(jìn)入invoke方法里面。

invoke方法:很簡單,它運(yùn)行首先通過class和method的過濾,看看是否需要攔截這個(gè)方法,如果被攔截,那么它就運(yùn)行interceptor的intercept方法。所以當(dāng)我們配置了簽名,就能夠攔截我們的方法。

我們先討論那么多,我們知道后面講插件的時(shí)候我們還會提及它,這里我們知道它會根據(jù)插件的個(gè)數(shù)生成一層層的代理對象就可以了。

executor的執(zhí)行

executor的執(zhí)行是依賴于Statement對象來操作的,讓我們以SimpleExecutor的doQuery方法為例子:

public class SimpleExecutor extends BaseExecutor {
......
 @Override
 public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  Statement stmt = null;
  try {
   Configuration configuration = ms.getConfiguration();
   StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
   stmt = prepareStatement(handler, ms.getStatementLog());
   return handler.<E>query(stmt, resultHandler);
  } finally {
   closeStatement(stmt);
  }
 }
 ......
 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  Statement stmt;
  Connection connection = getConnection(statementLog);
  stmt = handler.prepare(connection);
  handler.parameterize(stmt);
  return stmt;
 }
}

很顯然這里調(diào)度的是一個(gè)查詢方法

首先它先生成StatementHandler對象。

通過prepareStatement方法調(diào)用prepare方法初始化參數(shù)。

然后使用parameterize方法設(shè)置參數(shù)到運(yùn)行環(huán)境。

然后便通過handler.<E>query(stmt, resultHandler);方法來完成結(jié)果組裝。

于是我們的焦點(diǎn)就集中在了StatementHandler對象上,下章我們將談及它。

總結(jié)

以上所述是小編給大家介紹的Mybatis中SqlSession下的四大對象之執(zhí)行器(executor),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • JAVA反射機(jī)制實(shí)例詳解

    JAVA反射機(jī)制實(shí)例詳解

    這篇文章主要介紹了JAVA反射機(jī)制,以實(shí)例形式較為詳細(xì)的分析講解了Java反射機(jī)制的具體概念、功能與使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • 關(guān)于JSCH使用自定義連接池的說明

    關(guān)于JSCH使用自定義連接池的說明

    這篇文章主要介紹了關(guān)于JSCH使用自定義連接池的說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 解決版本不兼容Jar包沖突問題

    解決版本不兼容Jar包沖突問題

    在和三方對接的過程中,我們可能會不斷引入一些三方j(luò)ar包,但這個(gè)時(shí)候就有可能出現(xiàn)一個(gè)項(xiàng)目需要依賴兩個(gè)版本不同且功能不兼容的jar包,本文主要介紹了解決版本不兼容Jar包沖突問題,感興趣的可以了解一下
    2023-10-10
  • 一篇文章帶你了解Maven的坐標(biāo)概念以及依賴管理

    一篇文章帶你了解Maven的坐標(biāo)概念以及依賴管理

    這篇文章主要為大家介紹了Maven的坐標(biāo)概念以及依賴管理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Java?靜態(tài)代理與動態(tài)代理解析

    Java?靜態(tài)代理與動態(tài)代理解析

    這篇文章主要介紹了Java?靜態(tài)代理與動態(tài)代理解析,關(guān)于靜態(tài)代理與動態(tài)代理,一直是比較困擾很多新人開發(fā),但實(shí)際我們開發(fā)中,小到寫的某個(gè)工具類,大到經(jīng)常使用的Retrofit?其內(nèi)部都使用了動態(tài)代理,所以這篇文章從基礎(chǔ)到源碼解析,以便簡單理解靜態(tài)代理與Jdk中的動態(tài)代理
    2022-02-02
  • Java中通過Class類獲取Class對象的方法詳解

    Java中通過Class類獲取Class對象的方法詳解

    這篇文章主要給大家介紹了關(guān)于Java中通過Class類獲取Class對象的方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08
  • MyBatisPlus 主鍵策略的實(shí)現(xiàn)(4種)

    MyBatisPlus 主鍵策略的實(shí)現(xiàn)(4種)

    MyBatis Plus 集成了多種主鍵策略,幫助用戶快速生成主鍵,本文主要介紹了MyBatisPlus主鍵策略的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • mybatis中使用oracle關(guān)鍵字出錯(cuò)的解決方法

    mybatis中使用oracle關(guān)鍵字出錯(cuò)的解決方法

    這篇文章主要給大家介紹了關(guān)于mybatis中使用oracle關(guān)鍵字出錯(cuò)的解決方法,文中通過示例代碼將解決的方法介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-08-08
  • Java中static作用詳解

    Java中static作用詳解

    這篇文章主要介紹了Java中static作用,static表示“全局”或者“靜態(tài)”的意思,用來修飾成員變量和成員方法,也可以形成靜態(tài)static代碼塊,需要的朋友可以參考下
    2015-09-09
  • spring 如何解決循環(huán)依賴

    spring 如何解決循環(huán)依賴

    這篇文章主要介紹了spring 如何解決循環(huán)依賴,幫助大家更好的理解和學(xué)習(xí)使用spring框架,感興趣的朋友可以了解下
    2021-02-02

最新評論

遂昌县| 会东县| 太湖县| 绵竹市| 电白县| 浮山县| 惠安县| 社旗县| 滨州市| 梁山县| 淮安市| 安陆市| 莱州市| 来凤县| 泸定县| 宜黄县| 孝昌县| 榆树市| 屏边| 怀安县| 林芝县| 闵行区| 福海县| 尉氏县| 梨树县| 井陉县| 巴东县| 和田市| 长兴县| 吴川市| 丹东市| 中江县| 东乌珠穆沁旗| 新闻| 永福县| 灵武市| 汝州市| 南部县| 金堂县| 理塘县| 托克逊县|