# 動態代理 ###### tags: `Spring-代理模式` * 動態代理和靜態代理角色一樣 * 動態代理的代理類是動態生成的,不是我們直接寫 * 動態代理分為兩大類:基於接口的動態代理、基於類的動態代理 基於接口--JDK動態代理 基於類--cglib java字節碼實現:javassist 需要了解兩個類:Proxy 代理、InvocationHandler 調用處理程序 ## InvocationHandler nvocationHandler接口是proxy代理實例的調用處理程序實現的一個接口,每一個proxy代理實例都有一個關聯的調用處理程序;在代理實例調用方法時,方法調用被編碼分派到調用處理程序的invoke方法 ### 實現操作 1.接口 ```java= //租房 public interface Rent { public void rent(); } ``` 2.真實對象 ``` //房東 public class Host implements Rent { @Override public void rent() { System.out.println("房東要出租房子"); } } ``` **3.自動生成代理類** ```java= //我們會用這個類,自動生成代理類 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Rent rent; public void setRent(Rent rent){ this.rent = rent; } //生成得到代理類 public Object getProxy(){ //如果操作Proxy.newProxyInstance()傳回的代理物件,會呼叫invoke方法 return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); } //處理代理實例,並返回結果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //動態代理的本質,就是使用反射機制實現 //用反射(invoke),執行接口下的方法,args 參數 seeHouse(); Object result = method.invoke(rent, args); fare(); return result; } public void seeHouse(){ System.out.println("中介帶看房子"); } public void fare(){ System.out.println("收中介費"); } } ``` 4.客戶端 ```java= public class Client { public static void main(String[] args) { //真實角色 Host host = new Host(); //代理角色:現在沒有 ProxyInvocationHandler pih = new ProxyInvocationHandler(); //通過調用程序處理角色來處理我們要調用的接口對象 pih.setRent(host); Rent proxy = (Rent) pih.getProxy();//這裡的proxy就是動態實現生成的,我們並沒有寫 proxy.rent(); } } ``` ### 通用版 ```java= //我們會用這個類,自動生成代理類 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口(真實對象) private Object target; public void setTarget(Object target) { this.target = target; } //生成得到代理類 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //處理代理實例,並返回結果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //利用反射 log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String msg){ System.out.println("執行了" + msg + "方法"); } } ``` ### 動態代理的好處 * 可以使真實角色的操作更加純粹,不用去關注一些公共的業務 * 公共業務也就交給代理角色,實現了業務的分工 * 公共業務發生擴展的時候,方便集中管理 * 一個動態代理類代理的是一個接口,一般就是對應一類業務 * 一個動態代理類可以代理多個類,只要是實現同一個接口即可