一:什麼是動態代理:java
利用反射機制在運行時建立代理類。接口、被代理類不變。程序員
二:動態代理和靜態代理的不一樣:ide
一、靜態代理的代理類是程序員事先寫好的函數
二、動態代理的代理類是在程序運行時動態生成的this
三:動態代理分爲兩大類:spa
一、基於接口的動態代理代理
二、基於類的動態代理日誌
四:動態代理的三種實現方式:code
一、基於接口--->JDK動態代理 (JAVA原生的)(咱們在這裏使用)對象
二、基於類--->cglib (本身查閱資料作了解)
三、java字節碼實現---> javassist (查資料瞭解)
五:在使用動態代理以前,首先了解兩大類
一、Proxy (代理)
二、InvocationHandler (調用處理程序)
六:動態代理代碼展現 (房東出租房子案例)
一、建立一個抽象角色
1 //租房的接口 (抽象角色) 2 3 public interface Rent { 4 5 //出租的方法 6 void rent(); 7 8 }
二、建立真實角色,實現抽象角色接口
1 //房東 要出租房子 (真實的角色) 2 3 public class Host implements Rent { 4 @Override 5 public void rent() { 6 System.out.println("房東要出租房子"); 7 } 8 }
三、首先,咱們構建一個類來實現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 }
四、執行動態代理
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 }
五、輸出結果
七:動態代理的具體步驟
一、經過實現 InvocationHandler 接口建立本身的調用處理器;
二、經過爲 Proxy 類指定 ClassLoader 對象和一組 interface 來建立動態代理類;
三、經過反射機制得到動態代理類的構造函數,其惟一參數類型是調用處理器接口類型;
四、經過構造函數建立動態代理類實例,構造時調用處理器對象做爲參數被傳入。
八:動態代理的好處
一、可使真實角色的操做更加純粹!不用去關注一些公共的業務
二、公共業務就交給代理角色!實現了業務的分工!
三、公共業務發生擴展的時候,方便集中管理
四、一個動態代理類代理的是一個接口,通常就是對應的一類業務
五、一個動態代理類能夠代理多個類,只要是實現了同一個接口便可
九:根據上述的動態代理實現機制,咱們能夠衍生出一個萬能的動態代理類
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 }
注:抽象角色、真實角色 的實際代碼此處省略(與靜態代理實現步驟同樣)
【咱們可根據不一樣的業務需求,套用萬能動態代理模板便可】