摘要:靜態代理在代理模式中,通常指的時靜態代理。為實際類的接口,對應上面圖中的,為接口的接口有一個方法需要自己實現,我們委托代理類實現的額外功能便放在該方法里。這就是動態代理相對于靜態代理的意義。
代理模式是二十多種設計模式中的一個,屬于比較常用的設計模式。本質上就是用來委托我們生成的代理類去完成一些額外的功能,這樣能夠達到解耦、封裝的目的。
通常可以用在RPC、AOP中。比如在RPC中,當我們調用遠程方法時,需要委托代理類幫助我們去通過網絡連接遠程的服務提供者,幫助我們將消息編碼發送給服務端,幫我們接受服務端發來的結果。
在代理模式中,通常指的時靜態代理。
這是靜態代理的UML圖。代理的思想是:代理類ProxySubject擁有實際類RealSubject的相同方法doSomething(實現相同的一個接口),同時代理類內聚了實際類(即傳入實際類的一個引用),在代理類的doSomething方法中,通過實際類的引用調用實際類的doSomething方法,并在調用前后加入需要代理實現的額外功能。這樣我們就可以通過調用代理類的相同方法來達到我們的目的。
舉個例子:
interface Subject{ void doSomething(); }
class RealSubject implements Subject{ void doSomething(){ System.out.println("doSomething"); } }
class ProxySubject implements Subject{ private Subject target; public ProxySubject(Subject target){ this.target = target; } void doSomething(){ //do before System.out.println("do before"); target.doSomething();//調用realSubject的doSomething方法 //do after System.out.println("do after"); } }
class ProxyTest{ public static void main(String args[]){ //生成代理類,并將實際類傳入 ProxySubject proxy = new ProxySubject(new RealSubject()); proxy.doSomething(); } }
以上,通過代理類執行實際類相同的方法,我們可以運行額外的功能。這里不僅會運行實際類doSomething方法里面的打印“doSomething”,還會在之前打印“do before",之后打印”do after",這兩個即為額外的功能。
動態代理上面的靜態代理其實存在一個問題,一個實際類對應一個代理類,而很多時候需要代理實現的額外功能是相同的,比如我們要在A類的某個方法調用前打印“before”,B類的某個方法調用前打印“before”,C類也有這個需求,如果用靜態代理,我們需要寫A類的代理,B類的代理,C類的代理。。。這樣豈不是要累死。
java當中的動態代理就是為了這個解決這個問題。其實思路也很簡單,不用去管A類、B類、C類還是什么其他類,統一用反射調用實際類的方法。
java提供了動態代理類Proxy,使用其中的靜態方法Proxy.newProxyInstance(ClassLoader loader,Class>[] interfaces, InvocationHandler h)來動態生成代理類。interfaces為實際類的接口,對應上面圖中的Subject,loader為接口的Classloader,InvocationHandler接口有一個invoke方法需要自己實現,我們委托代理類實現的額外功能便放在該方法里。需要注意的是由此看出java的動態代理需要有接口才能使用。如果不用接口實現動態代理只能求助于cglib這類字節碼增強框架。
下面是動態代理的一般實現方法:
public class InvokeProxy implements InvocationHandler{ private Object target; public Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("do something before"); method.invoke(target, args); System.out.println("do something after"); return null; /* 如果反射調用的方法有返回值: Object result; result = method.invoke(target, args); return result; */ } }
同樣有接口Subject:
interface Subject{ void doSomething(); }
假設類A實現了Subject接口,可以根據如下代碼生成A的代理
public class ProxyTest { public static void main(String[] args) { Subject proxyA = (Subject)new InvokeProxy().bind(new A()); proxyA.doSomething(); } }
如果還有類B實現了Subject接口,我們只需更改上面的代碼即可,而不用像靜態代理那樣重復的編寫代碼。這就是動態代理相對于靜態代理的意義。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65781.html
摘要:我們今天也來做一個萬能遙控器設計模式適配器模式將一個類的接口轉換成客戶希望的另外一個接口。今天要介紹的仍然是創建型設計模式的一種建造者模式。設計模式的理論知識固然重要,但 計算機程序的思維邏輯 (54) - 剖析 Collections - 設計模式 上節我們提到,類 Collections 中大概有兩類功能,第一類是對容器接口對象進行操作,第二類是返回一個容器接口對象,上節我們介紹了...
摘要:類的適配器結構目標角色這就是所期待得到的接口,由于是類適配器模式,因此目標不可以是類。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。和適配器模式的關系適配器模式的用意是改變所考慮對象的接口,而代理模式不能改變。 點擊進入我的博客 3.1 適配器模式 適配器模式把一個類的接口變換成客戶端所期待的另一種接口,使得原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。 3...
摘要:又是什么其實就是一種實現動態代理的技術,利用了開源包,先將代理對象類的文件加載進來,之后通過修改其字節碼并且生成子類。 在實際研發中,Spring是我們經常會使用的框架,畢竟它們太火了,也因此Spring相關的知識點也是面試必問點,今天我們就大話Aop。特地在周末推文,因為該篇文章閱讀起來還是比較輕松詼諧的,當然了,更主要的是周末的我也在充電學習,希望有追求的朋友們也盡量不要放過周末時...
閱讀 584·2023-04-25 21:29
閱讀 1111·2023-04-25 21:27
閱讀 1050·2021-11-25 09:43
閱讀 1086·2021-09-29 09:43
閱讀 3619·2021-09-03 10:30
閱讀 2860·2019-08-29 15:26
閱讀 2811·2019-08-29 12:52
閱讀 1748·2019-08-29 11:10