一:什么是動態代理:
利用反射機制在運行時創建代理類,介面、被代理類不變,
二:動態代理和靜態代理的不同:
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 }
注:抽象角色、真實角色 的實際代碼此處省略(與靜態代理實作步驟一樣)
【我們可根據不同的業務需求,套用萬能動態代理模板即可】
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/138053.html
標籤:Java
