一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務(wù)器之家 - 編程語言 - Java教程 - Mybatis中SqlSession下的四大對象之執(zhí)行器(executor)

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

2021-07-30 11:39ykzhen2015 Java教程

mybatis中sqlsession下的四大對象是指:executor, statementHandler,parameterHandler,resultHandler對象。這篇文章主要介紹了Mybatis中SqlSession下的四大對象之執(zhí)行器(executor),需要的朋友可以參考下

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

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

executor在sqlsession中的應(yīng)用

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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í)行器會(huì)重用預(yù)處理語句(prepared statements)

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

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

?
1
2
3
4
5
<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):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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方法:

?
1
2
3
4
5
6
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è)方法是為了生成代理對象(占位)的。

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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方法:它會(huì)為我們生成代理對象。一旦我們的插件和它綁定,那么我們可以想到就會(huì)進(jìn)入invoke方法里面。

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

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

executor的執(zhí)行

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對服務(wù)器之家網(wǎng)站的支持!

原文鏈接:https://blog.csdn.net/ykzhen2015/article/details/50315027

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 5g影院天天爽爽 | 91高跟丝袜 | 日本一区二区三区精品 | bdsm酷刑折磨死美女 | 免费一级黄 | 无码国产成人午夜在线观看不卡 | 国产在线看片网站 | 久久久久久久电影 | 成人毛片1024你懂的 | 2048论坛永久入口 原创合集 | 亚洲国产精品高清在线 | 国产精品资源在线观看网站 | 国内精品视频一区二区三区 | 亚洲视频一区在线播放 | www射com | 日韩精品亚洲一级在线观看 | 成年人网站免费在线观看 | 亚洲好色网 | 国产九九| 午夜福利理论片高清在线 | 风间由美被义子中文字幕 | 亚洲国产自 | 欧美成a人片免费看久久 | 欧美高清免费一级在线 | 公妇乱淫 | 男人在女人下面狂躁 | 香蕉久久久久久狠狠色 | 日韩欧美一区二区三区 | 国产私人影院 | 好湿好紧太硬了我太爽了h 好湿好滑好硬好爽好深视频 | 色中色软件 | 亚洲图片综合网 | 9999网站 | 微福利92合集 | 九九影院午夜理论片无码 | 欧美高清无砖专区欧美精品 | julianann在厨房 | 国产精品毛片久久久久久久 | 加勒比京东热 | 亚洲男女在线 | 日本视频在线观看 |