色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Mybatis框架和插件將動態代理玩出了新境界

麻辣軟硬件 ? 來源:YXQ ? 2019-07-10 17:43 ? 次閱讀

靜態代理

又是一年畢業季,很多小伙伴開始去大城市打拼。來大城市第一件事就是租房,免不了和中介打交道,因為很多房東很忙,你根本找不到他。從這個場景中就可以抽象出來代理模式。

ISubject:被訪問者資源的抽象SubjectImpl:被訪問者具體實現類(房東)SubjectProxy:被訪問者的代理實現類(中介)

UML圖如下

舉個例子來理解一下這個設計模式老板讓記錄一下用戶服務的響應時間,用代理模式來實現這個功能。

public interface IUserService { public void request();}

public class UserServiceImpl implements IUserService { @Override public void request() { System.out.println(“this is userService”); }}

public class UserServiceProxy implements IUserService { private IUserService userService; public UserServiceProxy(IUserService userService) { this.userService = userService; } @Override public void request() { long startTime = System.currentTimeMillis(); userService.request(); System.out.println(“reques cost :” + (System.currentTimeMillis() - startTime)); } public static void main(String[] args) { IUserService userService = new UserServiceImpl(); UserServiceProxy userServiceProxy = new UserServiceProxy(userService); // this is userService // reques cost :0 userServiceProxy.request(); }}

一切看起來都非常的美好,老板又發話了,把產品服務的響應時間也記錄一下吧。又得寫如下3個類

IProductService ProductServiceImpl ProductServiceProxy

UserServiceProxy和ProductServiceProxy這兩個代理類的邏輯都差不多,卻還得寫2次。其實這個還好,如果老板說,把現有系統的幾十個服務的響應時間都記錄一下吧,你是不是要瘋了?這得寫多少代理類啊?

動態代理

黑暗總是暫時的,終究會迎來黎明,在JDK1.3之后引入了一種稱之為動態代理(Dynamic Proxy)的機制。使用該機制,我們可以為指定的接口在系統運行期間動態地生成代理對象,從而幫助我們走出最初使用靜態代理實現AOP的窘境

動態代理的實現主要由一個類和一個接口組成,即java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler接口。

讓我們用動態代理來改造一下上面記錄系統響應時間的功能。雖然要為IUserService和IProductService兩種服務提供代理對象,但因為代理對象中要添加的橫切邏輯是一樣的。所以我們只需要實現一個InvocationHandler就可以了。代碼如下

public class RequestCostInvocationHandler implements InvocationHandler { private Object target; public RequestCostInvocationHandler(Object target) { this.target = target; } /** 被代理對象的任何方法被執行時,都會先進入這個方法 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals(“request”)) { long startTime = System.currentTimeMillis(); // 執行目標對象的方法 method.invoke(target, args); System.out.println(“reques cost :” + (System.currentTimeMillis() - startTime)); } return null; } public static void main(String[] args) { // 3個參數解釋如下 // classloader,生成代理類 // 代理類應該實現的接口 // 實現InvocationHandler的切面類 IUserService userService = (IUserService) Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[]{IUserService.class}, new RequestCostInvocationHandler(new UserServiceImpl())); IProductService productService = (IProductService) Proxy.newProxyInstance(IProductService.class.getClassLoader(), new Class[]{IProductService.class}, new RequestCostInvocationHandler(new ProductServiceImpl())); // this is userService // reques cost :0 userService.request(); // this is productService // reques cost :0 productService.request(); }}

UML圖如下。恭喜你,你現在已經理解了Spring AOP是怎么回事了,就是這么簡單,今天先不展開談Spring

先簡單談談動態代理在Mybatis中是如何被大佬玩的出神入化的

Mybatis核心設計思路

相信用過mybatis的小伙伴都能理解下面這段代碼,通過roleMapper這個接口直接從數據庫中拿到一個對象

Role role = roleMapper.getRole(3L);

直覺告訴我,一個接口是不能運行的啊,一定有接口的實現類,可是這個實現類我自己沒寫啊,難道mybatis幫我們生成了?你猜的沒錯,mybatis利用動態代理幫我們生成了接口的實現類,這個類就是org.apache.ibatis.binding.MapperProxy,我先畫一下UML圖,MapperProxy就是下圖中的SubjectProxy類

和上面的UML類圖對比一下,發現不就少了一個SubjectImpl類嗎?那應該就是SubjectProxy類把SubjectImple類要做的事情做了唄,猜對了。SubjectProxy通過SubjectImple和SubjectImple.xml之間的映射關系知道自己應該執行什么SQL。所以mybatis最核心的思路就是這么個意思,細節之類的可以看源碼,理清最主要的思路,看源碼就能把握住重點。

Mybatis插件原理

mybatis的插件也用到了動態代理,還用到了責任鏈模式,我就不從源碼角度分析了。說一下大概實現,我們用插件肯定是為了在原先的基礎上增加新功能。增加一個插件,mybatis就在原先類的基礎上用動態代理生成一個代理對象,如果有多個插件,就在代理對象的基礎上再生成代理對象,形式和如下函數差不多

plugin2( plugin1( start() ) )

我再給你寫個例子,你再看看相關的源碼分析文章(也許我以后會寫),很快就能理解了。

在mybatis中要想用插件,有如下2個步驟1.在mybatis-config.xml中配置插件,如下所示

《plugins》 《plugin interceptor=“org.xrq.mybatis.plugin.FirstInterceptor” /》 《plugin interceptor=“org.xrq.mybatis.plugin.SecondInterceptor” /》《/plugins》

2.插件類還得實現Interceptor接口

我現在給一個需求,一個應用返回字符串0,我加一個插件在字符串的左右兩邊加plugin1,再加一個插件在字符串的左右兩邊加plugin2,開寫

返回字符串的接口

public interface IGetStr { public String getStrZero(); public String getStrOne();}

返回字符串的實現類

public class GetStrImpl implements IGetStr { @Override public String getStrZero() { return “0”; } @Override public String getStrOne() { return “1”; }}

定義攔截器接口

public interface Interceptor { /** 執行攔截邏輯的方法 */ Object intercept(Invocation invocation); /** * target是被攔截的對象,它的作用是給被攔截對象生成一個代理對象,并返回它。 * 為了方便,可以直接使用Mybatis中org.apache.ibatis.plugin類的wrap方法生成代理對象 * 我這里也寫了一個Plugin方法 */ Object plugin(Object target);}

看到一個不認識的類Invocation,定義如下

public class Invocation { private final Object target; private final Method method; private final Object[] args; public Invocation(Object target, Method method, Object[] args) { this.target = target; this.method = method; this.args = args; } public Object proceed() throws InvocationTargetException, IllegalAccessException { return method.invoke(target, args); }}

就是簡單的封裝了一下目標對象,目標方法和目標方法的參數。proceed方法就是執行目標對象的目標方法

Plugin算是一個工具類,生成代理對象

public class Plugin implements InvocationHandler { /** 目標對象 */ private final Object target; /** Interceptor對象 */ private final Interceptor interceptor; public Plugin(Object target, Interceptor interceptor) { this.target = target; this.interceptor = interceptor; } /** 生成代理對象 */ public static Object wrap(Object target, Interceptor interceptor) { return Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{IGetStr.class}, new Plugin(target, interceptor)); } /** 被代理對象的方法執行時,這個方法會被執行 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 只為方法getStrZero生成代理對象 if (method.getName().equals(“getStrZero”)) { return interceptor.intercept(new Invocation(target, method, args)); } return method.invoke(target, args); }}

寫第一個插件

public class FirstInterceptor implements Interceptor { /** 執行攔截邏輯的方法 */ @Override public Object intercept(Invocation invocation) { try { return “plugin1 ” + invocation.proceed() + “ plugin1”; } catch (Exception e) { return null; } } /** 為原先的類生成代理對象 */ @Override public Object plugin(Object target) { return Plugin.wrap(target, this); }}

有2個方法

plugin是為插件生成代理對象,用了我自己寫的Plugin工具類intercept是增加攔截邏輯,invocation.proceed()是執行目標對象的目標方法,前文說過了哈,這里我們只對輸出做了改變

第二個插件和第一個插件類似

public class SecondInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) { try { return “plugin2 ” + invocation.proceed() + “ plugin2”; } catch (Exception e) { return null; } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); }}

用一個容器保存插件,這里用到了責任鏈模式

public class InterceptorChain { /** 放攔截器 */ private final List《Interceptor》 interceptors = new ArrayList《Interceptor》(); public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; } public void addInterceptor(Interceptor interceptor) { interceptors.add(interceptor); }}

pluginAll方法是精髓,為每個插件一層一層的生成代理對象,就像套娃娃一樣。

驗證一下

public class Main { public static void main(String[] args) { // 配置插件 InterceptorChain interceptorChain = new InterceptorChain(); interceptorChain.addInterceptor(new FirstInterceptor()); interceptorChain.addInterceptor(new SecondInterceptor()); // 獲得代理對象 IGetStr getStr = new GetStrImpl(); getStr = (IGetStr) interceptorChain.pluginAll(getStr); String result = getStr.getStrZero(); // plugin2 plugin1 0 plugin1 plugin2 System.out.println(result); result = getStr.getStrOne(); // 1 System.out.println(result); }}

大功告成,可以看到先定義的插件先執行。

類有點多,如果看的有點暈,多看幾次,你就很容易理解了,我這里還是精簡了很多。

一個InvocationHandler接口被大佬玩出了新境界,果然編程這件事還得靠想象力。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 編程
    +關注

    關注

    88

    文章

    3619

    瀏覽量

    93777

原文標題:Mybatis框架和插件將動態代理玩出了新境界

文章出處:【微信號:VOSDeveloper,微信公眾號:麻辣軟硬件】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    JDK動態代理的原理

    在Java中,動態代理是一種機制,允許在運行時動態地創建代理對象來代替某個實際對象,從而在其前后執行額外的邏輯。 為什么JDK動態
    的頭像 發表于 09-30 10:51 ?587次閱讀

    數據庫整合Mybatis框架

    微服務 SpringBoot 20(九):整合Mybatis
    發表于 07-16 11:03

    請問mybatis分頁插件有哪些使用案列?

    mybatis分頁插件使用案例
    發表于 11-09 06:21

    java動態代理分析

    定義:為其他對象提供一種代理以控制對這個對象的訪問。 動態代理使用 java動態代理機制以巧妙的方式實現了
    發表于 09-27 15:14 ?0次下載

    mybatis是什么_MyBatis的優缺點詳解_mybatis框架入門詳解

    Mybatis框架是別人開發的一種半成品軟件,可以用來通過定制輔助快速開發是工具。MyBatis應用程序根據XML配置文件創建SqlSessionFactory,SqlSessionFactory在
    發表于 02-24 09:16 ?2w次閱讀

    mybatis動態sql詳解

    本文詳細介紹了mybatis執行動態sql語句的方法。
    發表于 02-24 11:37 ?3843次閱讀

    easy-mybatis Mybatis的增強框架

    ./oschina_soft/gitee-easy-mybatis.zip
    發表于 06-14 09:45 ?1次下載
    easy-<b class='flag-5'>mybatis</b> <b class='flag-5'>Mybatis</b>的增強<b class='flag-5'>框架</b>

    Fluent Mybatis、原生MybatisMybatis Plus對比

    mapper中再組裝參數。那對比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?
    的頭像 發表于 09-15 15:41 ?1444次閱讀

    一文掌握MyBatis動態SQL使用與原理

    摘要:使用動態 SQL 并非一件易事,但借助可用于任何 SQL 映射語句中的強大的動態 SQL 語言,MyBatis 顯著地提升了這一特性的易用性。
    的頭像 發表于 01-06 11:27 ?999次閱讀

    MyBatis-Plus為什么不支持聯表

    MyBatis Plus Join`一款專門解決MyBatis Plus 關聯查詢問題的擴展框架,他并不一款全新的框架,而是基于`MyBatis
    的頭像 發表于 02-28 15:19 ?2479次閱讀
    <b class='flag-5'>MyBatis</b>-Plus為什么不支持聯表

    Rust構建QEMU插件框架

    Cannonball 是一個用 Rust 構建 QEMU 插件框架!您可以在 C 語言的 QEMU TCG 插件中執行的任何操作,都可以使用cannonball。編寫以最小的開銷和盡可能多的功能運行的
    的頭像 發表于 07-21 16:57 ?914次閱讀

    MyBatis動態sql是什么?MyBatis動態SQL最全教程

    動態 SQL 是 MyBatis 的強大特性之一。在 JDBC 或其它類似的框架中,開發人員通常需要手動拼接 SQL 語句。根據不同的條件拼接 SQL 語句是一件極其痛苦的工作。
    的頭像 發表于 08-10 10:18 ?970次閱讀

    mybatis接口動態代理原理

    MyBatis是一款輕量級的Java持久化框架,它通過XML或注解配置的方式,數據庫操作與SQL語句解耦,提供了一種簡單、靈活的數據訪問方式。在MyBatis中,使用
    的頭像 發表于 12-03 11:52 ?958次閱讀

    mybatis和mybatisplus的區別

    MyBatisMyBatis Plus是兩個非常受歡迎的Java持久層框架。這兩個框架在設計和功能上有一些區別,下面我詳細介紹它們之間的
    的頭像 發表于 12-03 11:53 ?2571次閱讀

    mybatis框架的主要作用

    MyBatis框架是一種流行的Java持久化框架,主要用于簡化數據庫操作和管理。它提供了一種簡潔的方式來訪問數據庫,并將SQL語句從Java代碼中分離出來,從而提高了代碼的可維護性和可讀性
    的頭像 發表于 12-03 14:49 ?2044次閱讀
    主站蜘蛛池模板: 亚洲一区二区三区乱码在线欧洲| 办公室的秘密2中文字幕| 国产AV天堂亚洲AV麻豆| 秋霞网在线伦理影片| 国产GV天堂亚洲国产GV刚刚碰| 亚欧免费观看在线观看更新| 激情综合色| 99久久精品免费看国产一区二区三区| 日韩av无码在线直播| 国语对白刺激真实精品| 40岁东北老阿姨无码| 善良的女房东味道2在线观看| 国产最新地址| 99久久99久久久99精品齐| 色综合久久综合网观看| 精品少妇高潮蜜臀涩涩AV| seyeye免费高清观看| 亚州天堂在线视频av| 免费人成视频19674不收费| 国产精品久久国产三级国不卡顿| 亚洲欧洲一级| 日本粉嫩学生毛绒绒| 交换:年轻夫妇-HD中文字幕| 97色伦图片97色伦图影院久久| 天天色天天综合网| 两性午夜色视频免费网站| 国产成人高清亚洲一区app| 中文字幕亚洲乱码熟女在线| 四虎影院2022| 暖暖视频中国在线观看免费韩国 | 受坐在攻腿上H道具PLAY| 久久成人午夜电影mp4| 干性感美女| 69国产精品人妻无码免费| 亚洲AV无码一区二区色情蜜芽| 暖暖视频在线观看高清...| 国产综合18久久久久久软件| 成人 迅雷下载| 2020年国产理论| 亚洲日韩一区精品射精| 污文啊好棒棒啊好了|