什么是动态代理呢?
什么是動態代理呢?
就是在java的運行過程中,動態的生成的代理類。(為了更熟悉的了解動態代理,你必須先熟悉代理模式,可點擊設計模式之代理模式 閱讀)
我們知道java屬于解釋型語言,是在運行過程中,尋找字節碼文件從而實現類加載的。
但是字節碼文件并不需要一定是硬盤中的class文件,也可以是來自網絡、數據庫或者是直接生成的數據流。因此這就給虛擬機動態的生成代理類提供了可能。
Java 1.3 正式引入,動態代理(Dynamic proxies)特性。
前一篇文章我們已經知道Proxy是代理模式的核心,而動態代理就是在運行期間由虛擬機根據需要,動態的生成出這樣一個代理類。
我們可以直接看java的實現方法:
復制代碼
?1 import java.lang.reflect.InvocationHandler;
?2 import java.lang.reflect.Proxy;
?3?
?4 public class DynamicProxyInvoker
?5 {
?6 ? ? public static void main(String[] args)
?7 ? ? {
?8 ? ? ? ? InvocationHandler proxyHandler = new SuperStarInvocationHandler("messi");
?9 ? ? ? ? ISuperStar superStarDynamicProxy = (ISuperStar) Proxy.newProxyInstance(ISuperStar.class.getClassLoader(), new Class<?>[]
10 ? ? ? ? { ISuperStar.class }, proxyHandler);
11 ? ? ? ? superStarDynamicProxy.signContract();
12 ? ? ? ? superStarDynamicProxy.negotiate();
13 ? ? }
14 }
復制代碼
復制代碼
?1 import java.lang.reflect.InvocationHandler;
?2 import java.lang.reflect.Method;
?3?
?4 public class SuperStarInvocationHandler implements InvocationHandler
?5 {
?6 ? ? private String proxyName;
?7 ? ? ISuperStar superStar;
?8 ? ??
?9 ? ? public SuperStarInvocationHandler(String startName)
10 ? ? {
11 ? ? ? ? this.proxyName = startName + "'s proxy";
12 ? ? ? ? superStar = new SuperStar(startName);
13 ? ? }
14 ? ??
15 ? ? @Override
16 ? ? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
17 ? ? {
18 ? ? ? ? System.out.println(proxyName + " signContract"www.yongshiyule178.com);
19 ? ? ? ? Object object www.yigou521.com = method.invoke(superStar, args);
20 ? ? ? ? return object;
21 ? ? }
22 ? ??
23 }
復制代碼
復制代碼
?1 public interface ISuperStar
?2 {
?3 ? ? /**
?4 ? ? ?* 簽約
?5 ? ? ?*/
?6 ? ? public void signContract(www.gouyiflb.cn/);
?7 ? ??
?8 ? ? /**
?9 ? ? ?* 談判
10 ? ? ?*/
11 ? ? public void negotiate();
12 }
復制代碼
復制代碼
?1 public class SuperStar implements ISuperStar
?2 {
?3 ? ? private String starName;
?4 ? ? public SuperStar(String starName)
?5 ? ? {
?6 ? ? ? ? this.starName=starName;
?7 ? ? }
?8 ? ??
?9 ? ? @Override
10 ? ? public void signContract(www.tianjiuyule178.com)
11 ? ? {
12 ? ? ? ? System.out.println(starName+" signContract");
13 ? ? ? ? // to do sth
14 ? ? ? ? return;
15 ? ? }
16 ? ??
17 ? ? @Override
18 ? ? public void negotiate(www.yunshenpt.com)
19 ? ? {
20 ? ? ? ? System.out.www.dfgjyl.cn println(starName+" negotiate");
21 ? ? ? ? // to do sth
22 ? ? ? ? return;
23 ? ? }
24 }
復制代碼
superStarDynamicProxy是由系統自動生成的,一個實現了接口ISuperStar的類。這個類并不存在于具體的實現。同時由于系統也不知道我們具體需要在代理類中做哪些的操作。
因此需要我們自己提前安排好一個處理類SuperStarInvocationHandler。這個處理類中實現了代理類中是如何調用實現類中的方法的邏輯。
他們的調用關系圖是這樣的:
? ? ? ?我們可以看到動態代理的結構圖中,代理方并不會直接調用到被代理方,而是通過業務處理類來調用的。因此業務處理類需要保持一個被代理方的實例對象。(非強制)通過虛擬機主動生成動態代理類,我們可以發現,調用方和被調用方在代碼實現階段其實是斷層的。并不存在依次的直接調用關系。因此耦合的概念會更淺。同時由于不再需要為像靜態代理那樣為每個類都實現一個代理類,因此以切面的形式加入代理層成為可能。這個我會在后續的文章中介紹。
? ? ? ?ps :有興趣的同學可以在main方法中手動的將動態代理生成的代理方superStarDynamicProxy的字節碼導入到一個.class文件中,然后反編譯該文件。你就會發現,這個類其實就是被代理方所實現接口的一個適配類。其中的所有方法的實現都是調用業務處理類SuperStarInvocationHandler,再由業務處理類通過反射動態的調用到SuperStar類的。
動態代理的不足
1、早期由于jdk反射的性能有限,因此jdk的動態代理方式在性能上并不是很優越,但是隨著jdk對于反射性能的優化,此處的性能損耗已經越來越小。
2、從構建動態代理類的源碼(有興趣的同學也可以按照前文的形式反編譯),或者是手動添加一個Instance Proxy的形式。
我們可以發現,代理類其實是繼承自Proxy的同時實現了接口。因此動態代理只能用來解決接口動態代理的場景,因為java是不允許集成自多個類的。此問題可以使用CGLIB來解決,有興趣的同學可以自己看下,這個我會在后邊的文章中介紹。
如果你覺得寫的不錯,歡迎轉載和點贊。 轉載時請保留作者署名jilodream/王若伊_恩賜解脫(博客鏈接:http://www.cnblogs.com/jilodream/
總結
- 上一篇: JS实现歌词同步滚动效果
- 下一篇: 什么是数据增强(Data Augment