日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Mybatis Interceptor 拦截器原理 源码分析

發布時間:2024/4/14 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mybatis Interceptor 拦截器原理 源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Mybatis采用責任鏈模式,通過動態代理組織多個攔截器(插件),通過這些攔截器可以改變Mybatis的默認行為(諸如SQL重寫之類的),由于插件會深入到Mybatis的核心,因此在編寫自己的插件前最好了解下它的原理,以便寫出安全高效的插件。

代理鏈的生成

Mybatis支持對Executor、StatementHandler、PameterHandler和ResultSetHandler進行攔截,也就是說會對這4種對象進行代理。

?

通過查看Configuration類的源代碼我們可以看到,每次都對目標對象進行代理鏈的生成。

public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);return parameterHandler;} public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,ResultHandler resultHandler, BoundSql boundSql) {ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);return resultSetHandler;} public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);return statementHandler;} public Executor newExecutor(Transaction transaction, ExecutorType executorType, boolean autoCommit) {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, autoCommit);}executor = (Executor) interceptorChain.pluginAll(executor);return executor;}

接下來讓我們通過分析源代碼的方式來解讀Mybatis的攔截器實現原理

對于攔截器Mybatis為我們提供了一個Interceptor接口,通過實現該接口就可以定義我們自己的攔截器。我們先來看一下這個接口的定義:

?

1 package org.apache.ibatis.plugin;2 3 import java.util.Properties;4 5 public interface Interceptor {6 7 Object intercept(Invocation invocation) throws Throwable;8 9 Object plugin(Object target); 10 11 void setProperties(Properties properties); 12 13 }

?

?

我們可以看到在該接口中一共定義有三個方法,intercept、plugin和setProperties。plugin方法是攔截器用于封裝目標對象的,通過該方法我們可以返回目標對象本身,也可以返回一個它的代理。當返回的是代理的時候我們可以對其中的方法進行攔截來調用intercept方法,當然也可以調用其他方法,這點將在后文講解。setProperties方法是用于在Mybatis配置文件中指定一些屬性的。

定義自己的Interceptor最重要的是要實現plugin方法和intercept方法,在plugin方法中我們可以決定是否要進行攔截進而決定要返回一個什么樣的目標對象。而intercept方法就是要進行攔截的時候要執行的方法。

對于plugin方法而言,其實Mybatis已經為我們提供了一個實現。Mybatis中有一個叫做Plugin的類,里面有一個靜態方法wrap(Object target,Interceptor interceptor),通過該方法可以決定要返回的對象是目標對象還是對應的代理。這里我們先來看一下Plugin的源碼:

1 package org.apache.ibatis.plugin;2 3 import java.lang.reflect.InvocationHandler;4 import java.lang.reflect.Method;5 import java.lang.reflect.Proxy;6 import java.util.HashMap;7 import java.util.HashSet;8 import java.util.Map;9 import java.util.Set;10 11 import org.apache.ibatis.reflection.ExceptionUtil;12 13 //這個類是Mybatis攔截器的核心,大家可以看到該類繼承了InvocationHandler14 //又是JDK動態代理機制15 public class Plugin implements InvocationHandler {16 17 //目標對象18 private Object target;19 //攔截器20 private Interceptor interceptor;21 //記錄需要被攔截的類與方法22 private Map<Class<?>, Set<Method>> signatureMap;23 24 private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {25 this.target = target;26 this.interceptor = interceptor;27 this.signatureMap = signatureMap;28 }29 30 //一個靜態方法,對一個目標對象進行包裝,生成代理類。31 public static Object wrap(Object target, Interceptor interceptor) {32 //首先根據interceptor上面定義的注解 獲取需要攔截的信息33 Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);34 //目標對象的Class35 Class<?> type = target.getClass();36 //返回需要攔截的接口信息37 Class<?>[] interfaces = getAllInterfaces(type, signatureMap);38 //如果長度為>0 則返回代理類 否則不做處理39 if (interfaces.length > 0) {40 return Proxy.newProxyInstance(41 type.getClassLoader(),42 interfaces,43 new Plugin(target, interceptor, signatureMap));44 }45 return target;46 }47 48 //代理對象每次調用的方法49 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {50 try {51 //通過method參數定義的類 去signatureMap當中查詢需要攔截的方法集合52 Set<Method> methods = signatureMap.get(method.getDeclaringClass());53 //判斷是否需要攔截54 if (methods != null && methods.contains(method)) {55 return interceptor.intercept(new Invocation(target, method, args));56 }57 //不攔截 直接通過目標對象調用方法58 return method.invoke(target, args);59 } catch (Exception e) {60 throw ExceptionUtil.unwrapThrowable(e);61 }62 }63 64 //根據攔截器接口(Interceptor)實現類上面的注解獲取相關信息65 private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) {66 //獲取注解信息67 Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);68 //為空則拋出異常69 if (interceptsAnnotation == null) { // issue #25170 throw new PluginException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName()); 71 }72 //獲得Signature注解信息73 Signature[] sigs = interceptsAnnotation.value();74 Map<Class<?>, Set<Method>> signatureMap = new HashMap<Class<?>, Set<Method>>();75 //循環注解信息76 for (Signature sig : sigs) {77 //根據Signature注解定義的type信息去signatureMap當中查詢需要攔截方法的集合78 Set<Method> methods = signatureMap.get(sig.type());79 //第一次肯定為null 就創建一個并放入signatureMap80 if (methods == null) {81 methods = new HashSet<Method>();82 signatureMap.put(sig.type(), methods);83 }84 try {85 //找到sig.type當中定義的方法 并加入到集合86 Method method = sig.type().getMethod(sig.method(), sig.args());87 methods.add(method);88 } catch (NoSuchMethodException e) {89 throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e, e);90 }91 }92 return signatureMap;93 }94 95 //根據對象類型與signatureMap獲取接口信息96 private static Class<?>[] getAllInterfaces(Class<?> type, Map<Class<?>, Set<Method>> signatureMap) {97 Set<Class<?>> interfaces = new HashSet<Class<?>>();98 //循環type類型的接口信息 如果該類型存在與signatureMap當中則加入到set當中去99 while (type != null) { 100 for (Class<?> c : type.getInterfaces()) { 101 if (signatureMap.containsKey(c)) { 102 interfaces.add(c); 103 } 104 } 105 type = type.getSuperclass(); 106 } 107 //轉換為數組返回 108 return interfaces.toArray(new Class<?>[interfaces.size()]); 109 } 110 111 } Plugin源代碼分析

?

下面是倆個注解類的定義源碼

1 package org.apache.ibatis.plugin;2 3 import java.lang.annotation.ElementType;4 import java.lang.annotation.Retention;5 import java.lang.annotation.RetentionPolicy;6 import java.lang.annotation.Target;7 8 @Retention(RetentionPolicy.RUNTIME)9 @Target(ElementType.TYPE) 10 public @interface Intercepts { 11 Signature[] value(); 12 } 1 package org.apache.ibatis.plugin;2 3 import java.lang.annotation.ElementType;4 import java.lang.annotation.Retention;5 import java.lang.annotation.RetentionPolicy;6 import java.lang.annotation.Target;7 8 @Retention(RetentionPolicy.RUNTIME)9 @Target(ElementType.TYPE) 10 public @interface Signature { 11 Class<?> type(); 12 13 String method(); 14 15 Class<?>[] args(); 16 }

http://www.cnblogs.com/daxin/p/3541922.html

?

總結

以上是生活随笔為你收集整理的Mybatis Interceptor 拦截器原理 源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久精品人妻av一区二区三区 | 亚洲伦理网 | 91精品国产一区二区三区蜜臀 | 欧美在线 | 亚洲 | 国产超碰精品 | 日韩欧美无 | 中文字母av | 久久视频免费观看 | 精品一区二区三区成人免费视频 | 国产精品3p视频 | www免费黄色 | 一本大道久久久久精品嫩草 | 永久免费av网站 | 脱美女衣服亲摸揉视频 | 黄色一级大片免费看 | 中文字幕av网 | 精品少妇一二三区 | 成年人av电影 | 色综合一区二区 | 久久综合色婷婷 | 吻胸摸激情床激烈视频 | 午夜写真片福利电影网 | 久久影视av| av资源首页 | 3344成人| 综合xx网| 色综合五月| 成人免费看类便视频 | 国产精品日韩av | 亚洲国内精品 | 91偷拍视频| 一区二区三区在线电影 | 亚洲无码精品在线观看 | 91精品福利在线 | 午夜精品久久久久久久久久久久久 | 国产精品精品视频 | 手机在线免费看av | 另类小说欧美 | 麻豆成人久久精品一区二区三区 | 久久99精品久久久久 | 成年人在线播放 | 黄色成年人视频 | 久久潮 | 亚洲国产精品午夜久久久 | 69精品久久久久久 | 国产美女主播在线 | 精东传媒在线观看 | 欧美男人又粗又长又大 | 日日夜夜爽| 中国av在线 | 日韩精品成人免费观看视频 | 四虎影视最新网址 | 国产亚洲视频一区 | 日韩精品自拍 | 午夜aaa | 无码国产精品一区二区免费16 | 99久久99久久久精品棕色圆 | 欧美色射 | 国产调教在线观看 | 亚洲一区电影网 | a天堂在线 | 少妇高潮一区二区三区99小说 | 国内毛片毛片 | 就爱av| 免费黄色av片 | 佐佐木明希av在线 | 老熟妻内射精品一区 | www日韩欧美 | 欧美一区二区三区视频 | 大粗鳮巴久久久久久久久 | 91大神一区二区 | 日韩免费视频观看 | 日韩在线影院 | 婷婷综合另类小说色区 | 中日韩精品一区二区三区 | 人人看人人爽 | 久久精品6 | 日韩欧美视频在线免费观看 | 久久九九久久九九 | 国产h自拍 | 亚洲激情国产 | 日本人做爰全过程 | 国产精品久久国产精品 | 色呦呦国产 | 国产精品免费观看视频 | 成年人黄色大片 | 亚洲精品少妇久久久久久 | 先锋影音亚洲 | aⅴ天堂网 | babes性欧美69| 可以看黄色的网站 | 欧美午夜性| 天天操国产 | 红猫大本营在线观看的 | 999av视频| 亚洲精品白浆高清久久久久久 | 中国一级黄色大片 | 日本黄色免费大片 | 新97超碰|