一:什麼是動態代理: 利用反射機制在運行時創建代理類。介面、被代理類不變。 二:動態代理和靜態代理的不同: 1、靜態代理的代理類是程式員事先寫好的 2、動態代理的代理類是在程式運行時動態生成的 三:動態代理分為兩大類: 1、基於介面的動態代理 2、基於類的動態代理 四:動態代理的三種實現方式: 1、 ...
一:什麼是動態代理:
利用反射機制在運行時創建代理類。介面、被代理類不變。
二:動態代理和靜態代理的不同:
1、靜態代理的代理類是程式員事先寫好的
2、動態代理的代理類是在程式運行時動態生成的
三:動態代理分為兩大類:
1、基於介面的動態代理
2、基於類的動態代理
四:動態代理的三種實現方式:
1、基於介面--->JDK動態代理 (JAVA原生的)(我們在這裡使用)
2、基於類--->cglib (自己查閱資料做瞭解)
3、java位元組碼實現---> javassist (查資料瞭解)
五:在使用動態代理之前,首先瞭解兩大類
1、Proxy (代理)
2、InvocationHandler (調用處理程式)
六:動態代理代碼展示 (房東出租房子案例)
1、創建一個抽象角色
1 //租房的介面 (抽象角色) 2 3 public interface Rent { 4 5 //出租的方法 6 void rent(); 7 8 }
2、創建真實角色,實現抽象角色介面
1 //房東 要出租房子 (真實的角色) 2 3 public class Host implements Rent { 4 @Override 5 public void rent() { 6 System.out.println("房東要出租房子"); 7 } 8 }
3、首先,我們構建一個類來實現InvocationHandler介面
1 //動態生成代理 2 3 public class ProxyInvocationHandler implements InvocationHandler { 4 5 //被代理的介面 6 private Rent rent; 7 8 public void setRent(Rent rent) { 9 this.rent = rent; 10 } 11 12 // Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 13 // new Class<?>[] { Foo.class }, 14 // handler); 15 16 //生成得到代理類 (通過Proxy類的靜態方法newProxyInstance返回一個介面的代理實例。針對不同的代理類,傳入相應的代理程式控制器InvocationHandler) 17 public Object getProxy(){ 18 return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); 19 20 } 21 22 //處理代理實例,並返回結果 23 @Override 24 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 25 26 //動態代理的本質,就是使用反射機制實現! 27 seeHouse(); 28 Object result = method.invoke(rent, args); 29 fare(); 30 return result; 31 } 32 33 public void seeHouse(){ 34 System.out.println("中介帶看房子!"); 35 } 36 public void fare(){ 37 System.out.println("收中介費!"); 38 } 39 }
4、執行動態代理
1 //執行動態代理,實現租房方法 2 3 public class Client { 4 public static void main(String[] args) { 5 //真實角色 6 Host host = new Host(); 7 8 //代理角色,現在沒有 9 ProxyInvocationHandler pih = new ProxyInvocationHandler(); 10 //通過調用程式來處理我們要調用的介面對象! 11 pih.setRent(host); 12 13 Rent proxy = (Rent) pih.getProxy(); //這裡的proxy是動態生成的,我們並沒有寫! 14 //調用租房方法 15 proxy.rent(); 16 17 } 18 }
5、輸出結果
七:動態代理的具體步驟
1、通過實現 InvocationHandler 介面創建自己的調用處理器;
2、通過為 Proxy 類指定 ClassLoader 對象和一組 interface 來創建動態代理類;
3、通過反射機制獲得動態代理類的構造函數,其唯一參數類型是調用處理器介面類型;
4、通過構造函數創建動態代理類實例,構造時調用處理器對象作為參數被傳入。
八:動態代理的好處
1、可以使真實角色的操作更加純粹!不用去關註一些公共的業務
2、公共業務就交給代理角色!實現了業務的分工!
3、公共業務發生擴展的時候,方便集中管理
4、一個動態代理類代理的是一個介面,一般就是對應的一類業務
5、一個動態代理類可以代理多個類,只要是實現了同一個介面即可
九:根據上述的動態代理實現機制,我們可以衍生出一個萬能的動態代理類
1 //萬能的動態代理類 2 3 public class ProxyInvocationHandler implements InvocationHandler { 4 5 //被代理的介面 6 private Object target; 7 8 public void setTarget(Object target) { 9 this.target = target; 10 } 11 12 // Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 13 // new Class<?>[] { Foo.class }, 14 // handler); 15 16 //生成得到代理類 17 public Object getProxy(){ 18 return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); 19 20 } 21 22 //處理代理實例,並返回結果 23 @Override 24 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 25 26 //動態代理的本質,就是使用反射機制實現! 27 log(method.getName()); 28 Object result = method.invoke(target, args); 29 return result; 30 } 31 32 //根據不同業務需要,創建不同的擴展方法 (此處為列印日誌) 33 public void log(String msg){ 34 System.out.println("執行了"+msg+"方法!"); 35 } 36 }
執行動態代理:
1 //執行動態代理 2 3 public class Client { 4 public static void main(String[] args) { 5 //真實角色 6 UserServiceImpl userService = new UserServiceImpl(); 7 8 //代理角色,不存在 9 ProxyInvocationHandler pih = new ProxyInvocationHandler(); 10 11 //設置要代理的對象 12 pih.setTarget(userService); 13 14 //動態生成代理類 15 UserService proxy = (UserService) pih.getProxy(); 16 17 proxy.update(); 18 19 } 20 }
註:抽象角色、真實角色 的實際代碼此處省略(與靜態代理實現步驟一樣)
【我們可根據不同的業務需求,套用萬能動態代理模板即可】