<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在代理模式(Proxy Pattern)屬於結構型模式。在代理模式中,我們對一個物件提供一個代理物件,使用代理物件控制原物件的參照,目的是為了透明的控制物件存取
Java中的代理按照代理類生成時機不同分為靜態代理和動態代理,靜態代理的代理類在編譯器就生成,而動態代理的代理類在Java執行時動態生成。動態代理又分為JDK代理和CGLib代理。
業務程式碼
/** * 靜態代理 */ public interface Pay { void pay(); } //真實類 class Alipay implements Pay { @Override public void pay() { System.out.println("支付寶支付"); } } //代理類 class AlipayProxy implements Pay{ //組合真實物件 private final Alipay alipay = new Alipay(); @Override public void pay() { long startTime = System.currentTimeMillis(); alipay.pay(); System.out.println("執行了" + (System.currentTimeMillis()-startTime) + "毫秒"); //支付寶支付 執行了0毫秒 } }
測試程式碼
public class Client { public static void main(String[] args) { new AlipayProxy().pay(); } }
優點
缺點
為了彌補靜態代理的缺點,引入了動態代理
1.JDK動態代理(利用Java提供的代理機制)
業務程式碼
/** * JDK動態代理 */ public interface Pay { void pay(); } //真實類 class Alipay implements Pay { @Override public void pay() { System.out.println("支付寶支付"); } } class PayProxy { //組合真實物件 private Pay pay; public PayProxy(Pay pay) { this.pay = pay; } public Pay getProxy() { return (Pay) Proxy.newProxyInstance(getClass().getClassLoader(), pay.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); Object result = method.invoke(pay, args); System.out.println("執行了" + (System.currentTimeMillis() - startTime) + "毫秒"); return result; } }); } }
測試程式碼
public class Client { public static void main(String[] args) { PayProxy payProxy = new PayProxy(new Alipay()); Pay pay = payProxy.getProxy(); pay.pay(); //支付寶支付 執行了0毫秒 } }
我們通過arthas工具進行反編譯,可以找到真正的代理類$Proxy0
//代理物件 public final class $Proxy0 extends Proxy implements Pay { private static Method m3; public $Proxy0(InvocationHandler invocationHandler) { super(invocationHandler); } static { // 通過反射獲取名叫pay的menthod m3 = Class.forName("com.designpattern.structure.proxy.v2.Pay").getMethod("pay", new Class[0]); return; } public final void pay() { // h是invocationHandler物件 this.h.invoke(this, m3, null); return; } }
總結執行流程如下
2.CGLib動態代理
JDK動態代理要求必須定義介面,如果沒有定義介面,就可以使用CGLib動態代理,CGLib為JDK的動態代理提供了很好的補充
首先引入cglib-3.3.0.jar與asm-9.0.jar
業務程式碼
//真實物件 class Alipay implements Pay { @Override public void pay() { System.out.println("支付寶支付"); } } class AlipayProxy implements MethodInterceptor { //組合真實物件 private Alipay alipay = new Alipay(); public Alipay getProxy(){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Alipay.class); //設定回撥函數 enhancer.setCallback(this); //返回代理物件 return (Alipay) enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { long startTime = System.currentTimeMillis(); Object result = method.invoke(alipay, args); System.out.println("執行了" + (System.currentTimeMillis() - startTime) + "毫秒"); return result; } }
測試程式碼
public class Client { public static void main(String[] args) { Alipay proxy = new AlipayProxy().getProxy(); proxy.pay(); //支付寶支付 執行了0毫秒 } }
優點
缺點
1.功能擴充套件:紀錄檔、監控、事務
2.控制管理:許可權、限流
3.遠端代理:FeignClient、RMI
4.動態邏輯:mybatis mapper、jpa
5.延遲載入:虛代理
上文提到靜態代理是一個具體類產生一個代理類,可能會造成類爆炸,我們現在反觀動態代理則是一個介面產生一個代理類,也可能會造成類爆炸,所以這裡給出一個較為通用的實現
業務程式碼
//記錄執行的時間的通用類 public class TimeRecordProxy<T> { private final T target; public TimeRecordProxy(T target) { this.target = target; } @SuppressWarnings("unchecked") public T getProxy() { return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this::invoke); } private Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException { long startTime = System.currentTimeMillis(); Object result = method.invoke(target, args); System.out.println("執行了" + (System.currentTimeMillis()-startTime) + "毫秒"); return result; } }
測試程式碼
public class Client { public static void main(String[] args) { TimeRecordProxy<Pay> timeRecordProxy = new TimeRecordProxy<>(new Alipay()); timeRecordProxy.getProxy().pay(); //支付寶支付 執行了0毫秒 } }
Spring AOP是代理模式的典型應用
到此這篇關於Java結構型模式之代理模式詳解的文章就介紹到這了,更多相關Java代理模式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45