摘要:插件插件接口在中使用插件,我們必須實現(xiàn)接口。它將直接覆蓋你所攔截對象原有的方法,因此它是插件的核心方法。插件在對象中的保存插件的代理和反射設(shè)計插件用的是責(zé)任鏈模式,的責(zé)任鏈?zhǔn)怯扇ザx的。
插件 1、插件接口
在MyBatis中使用插件,我們必須實現(xiàn)接口Interceptor。
public interface Interceptor { // 它將直接覆蓋你所攔截對象原有的方法,因此它是插件的核心方法。 // Intercept里面有個參數(shù)Invocation對象,通過它可以反射調(diào)度原來對象的方法 Object intercept(Invocation invocation) throws Throwable; // 作用是給被攔截對象生成一個代理對象,并返回它。target是被攔截對象 Object plugin(Object target); // 允許在plugin元素中配置所需參數(shù),方法在插件初始化的時候就被調(diào)用了一次 void setProperties(Properties properties); }2、插件初始化
插件的初始化是在MyBatis初始化的時候完成的。
public class XMLConfigBuilder extends BaseBuilder { ...... private void pluginElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { String interceptor = child.getStringAttribute("interceptor"); Properties properties = child.getChildrenAsProperties(); Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance(); interceptorInstance.setProperties(properties); configuration.addInterceptor(interceptorInstance); } } } }
在解析配置文件的時候,在MyBatis的上下文初始化過程中,就開始讀入插件節(jié)點和我們配置的參數(shù),同時使用反射技術(shù)生成對應(yīng)的插件實例,然后調(diào)用插件方法中的setProperties方法,設(shè)置我們配置的參數(shù),然后將插件實例保存到配置對象中,以便讀取和使用它。
插件在Configuration對象中的保存:
public void addInterceptor(Interceptor interceptor) { interceptorChain.addInterceptor(interceptor); }3、插件的代理和反射設(shè)計
插件用的是責(zé)任鏈模式,MyBatis的責(zé)任鏈?zhǔn)怯蒳nterceptorChain去定義的。在MyBatis創(chuàng)建Executor執(zhí)行器的時候,我們可以看到有如下的一段代碼:
executor = (Executor) interceptorChain.pluginAll(executor);
再看下Interceptor的pluginAll方法:
public class InterceptorChain { private final Listinterceptors = new ArrayList (); public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { // plugin方法是生成代理對象的方法 // 可以看出來,如果有多個插件的話,會生成多層代理的代理對象 target = interceptor.plugin(target); } return target; } ...... }
MyBatis為我們提供了Plugin類用于生成代理對象。
public class Plugin implements InvocationHandler { ...... public static Object wrap(Object target, Interceptor interceptor) { Map, Set > 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 methods = signatureMap.get(method.getDeclaringClass()); // 如果存在簽名的攔截方法,插件的intercept方法將被調(diào)用 if (methods != null && methods.contains(method)) { return interceptor.intercept(new Invocation(target, method, args)); } // 否則,直接反射調(diào)度我們要執(zhí)行的方法 return method.invoke(target, args); } catch (Exception e) { throw ExceptionUtil.unwrapThrowable(e); } } }
在調(diào)用插件的攔截方法時,可以看到傳遞了一個新創(chuàng)建的Invocation對象。
interceptor.intercept(new Invocation(target, method, args));
Invocation類封裝了被代理的對象、方法及其參數(shù)。
public class Invocation { public Invocation(Object target, Method method, Object[] args) { this.target = target; this.method = method; this.args = args; } // 這個方法會調(diào)度被代理對象的真實方法, 所以我們通過這個方法直接調(diào)用被代理對象原來的方法 // 如果多個插件的話,我們知道會生成多層代理對象,那么每層被代理都可以通過Invocation調(diào)用這個proceed方法, // 所以在多個插件的環(huán)境下,調(diào)度proceed()方法時,MyBatis總是從最后一個代理對象運行到第一個代理對象, // 最后是真實被攔截的對象方法被運行 public Object proceed() throws InvocationTargetException, IllegalAccessException { return method.invoke(target, args); } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69549.html
摘要:的解析和運行原理構(gòu)建過程提供創(chuàng)建的核心接口。在構(gòu)造器初始化時會根據(jù)和的方法解析為命令。數(shù)據(jù)庫會話器定義了一個對象的適配器,它是一個接口對象,構(gòu)造器根據(jù)配置來適配對應(yīng)的對象。它的作用是給實現(xiàn)類對象的使用提供一個統(tǒng)一簡易的使用適配器。 MyBatis的解析和運行原理 構(gòu)建SqlSessionFactory過程 SqlSessionFactory提供創(chuàng)建MyBatis的核心接口SqlSess...
摘要:學(xué)習(xí)筆記有官方的中文開發(fā)文檔并且針對使用者比較友好是一款優(yōu)秀的持久層框架,它支持定制化存儲過程以及高級映射。它只和配置有關(guān),存在的意義僅在于用來減少類完全限定名的冗余,為了簡化中的書寫。 Mybatis學(xué)習(xí)筆記 mybatis有官方的中文開發(fā)文檔并且針對使用者比較友好:http://www.mybatis.org/mybatis-3/zh/ MyBatis 是一款優(yōu)秀的持久層框架,它支...
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:插件功能非常強大,,方法跳轉(zhuǎn)提示,分頁插件。三地址使用該插件在引入該插件具體使用,我們在以后的中再學(xué)習(xí)具體的方法。更多請參考學(xué)習(xí)筆記一入門 mybatis 插件功能非常強大,mybatis-generator,mybatis-plugin方法跳轉(zhuǎn)提示,mybatis-pagehelper分頁插件。 一、mybatis-generator 1、mybatis-generator配置 先在...
閱讀 1951·2021-09-07 09:59
閱讀 2520·2019-08-29 16:33
閱讀 3688·2019-08-29 16:18
閱讀 2849·2019-08-29 15:30
閱讀 1678·2019-08-29 13:52
閱讀 2035·2019-08-26 18:36
閱讀 530·2019-08-26 12:19
閱讀 694·2019-08-23 15:23