什麼是動態代理呢?
就是在java的運行過程當中,動態的生成的代理類。(爲了更熟悉的瞭解動態代理,你必須先熟悉代理模式,可點擊設計模式之代理模式 閱讀)
咱們知道java屬於解釋型語言,是在運行過程當中,尋找字節碼文件從而實現類加載的。
可是字節碼文件並不須要必定是硬盤中的class文件,也能夠是來自網絡、數據庫或者是直接生成的數據流。所以這就給虛擬機動態的生成代理類提供了可能。
Java 1.3 正式引入,動態代理(Dynamic proxies)特性。
前一篇文章咱們已經知道Proxy是代理模式的核心,而動態代理就是在運行期間由虛擬機根據須要,動態的生成出這樣一個代理類。
咱們能夠直接看java的實現方法:html
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"); 19 Object object = method.invoke(superStar, args); 20 return object; 21 } 22 23 }
1 public interface ISuperStar 2 { 3 /** 4 * 簽約 5 */ 6 public void signContract(); 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() 11 { 12 System.out.println(starName+" signContract"); 13 // to do sth 14 return; 15 } 16 17 @Override 18 public void negotiate() 19 { 20 System.out.println(starName+" negotiate"); 21 // to do sth 22 return; 23 } 24 }
superStarDynamicProxy是由系統自動生成的,一個實現了接口ISuperStar的類。這個類並不存在於具體的實現。同時因爲系統也不知道咱們具體須要在代理類中作哪些的操做。
所以須要咱們本身提早安排好一個處理類SuperStarInvocationHandler。這個處理類中實現了代理類中是如何調用實現類中的方法的邏輯。
他們的調用關係圖是這樣的:java
咱們能夠看到動態代理的結構圖中,代理方並不會直接調用到被代理方,而是經過業務處理類來調用的。所以業務處理類須要保持一個被代理方的實例對象。(非強制)經過虛擬機主動生成動態代理類,咱們能夠發現,調用方和被調用方在代碼實現階段實際上是斷層的。並不存在依次的直接調用關係。所以耦合的概念會更淺。同時因爲再也不須要爲像靜態代理那樣爲每一個類都實現一個代理類,所以以切面的形式加入代理層成爲可能。這個我會在後續的文章中介紹。數據庫
ps :有興趣的同窗能夠在main方法中手動的將動態代理生成的代理方superStarDynamicProxy的字節碼導入到一個.class文件中,而後反編譯該文件。你就會發現,這個類其實就是被代理方所實現接口的一個適配類。其中的全部方法的實現都是調用業務處理類SuperStarInvocationHandler,再由業務處理類經過反射動態的調用到SuperStar類的。設計模式
動態代理的不足網絡
一、早期因爲jdk反射的性能有限,所以jdk的動態代理方式在性能上並非很優越,可是隨着jdk對於反射性能的優化,此處的性能損耗已經愈來愈小。
二、從構建動態代理類的源碼(有興趣的同窗也能夠按照前文的形式反編譯),或者是手動添加一個Instance Proxy的形式。
咱們能夠發現,代理類實際上是繼承自Proxy的同時實現了接口。所以動態代理只能用來解決接口動態代理的場景,由於java是不容許集成自多個類的。此問題可使用CGLIB來解決,有興趣的同窗能夠本身看下,這個我會在後邊的文章中介紹。ide