一 ,什麼是代理? java
代理 : 原本是本身應該作的事, 卻請了別人來作, 被請的人就是代理對象數組
舉例 : 春節回家買票找人代買, 黃牛就是代理對象學習
二 ,什麼是動態代理? 測試
代理的對象是變更的, 在程序運行過程當中產生的 . 而在程序運行過程當中產生對象, 這個對象是不固定的, 那麼能夠經過反射來實現, 因此動態代理是基於反射實現的.this
三 ,動態代理常見有JDK提供的動態代理,和Cglib提供的代理 , 此次介紹JDK提供的代理spa
1, 在Java中java.lang.reflect包下提供了一個Proxy類和InvocationHandler接口,經過使用這個類和接口就能夠生成動態代理對象. JDK提供的代理只能針對接口作代理. Cglib提供的代理會更強大一些..net
2, Proxy類中的方法建立動態代理類對象,該方法會返回代理類代理
Public static Object newProxyInstance(ClassLoader loader, Class<?>[] intergaces,InvocationHandler h )日誌
最終會調用InvocationHandler的方法code
3, InvocationHandler接口 , 定義動態代理要實現的具體業務邏輯
Object invoke(Objectproxy, Method method , Object[] args );
自定義類實現IncovationHandler接口, 複寫invoke()方法, 具體代理的邏輯寫在該方法中. invoke()方法執行後的返回值爲代理對象 .
代碼舉例:
1,建立要代理的接口和實現類
public interface UserDao { void add(); void delete(); } public class UserDaoImp implements UserDao{ public void add() { System.out.println("執行了添加的方法"); } public void delete() { System.out.println("執行了刪除的方法"); } } public interface WorkDao { void work(); void study(); } public class WorkDaoImp implements WorkDao { public void work() { System.out.println("工做"); } public void study() { System.out.println("學習"); } }
2,建立InvocationHandler接口的實現類,具體代理的業務邏輯在Invoke方法
/** * 自定義類實現IncovationHandler接口, 複寫invoke()方法 */ public class MyInvocationHandler implements InvocationHandler { private Object target; //目標對象 public MyInvocationHandler(Object target){ this.target = target; } /** * 在代理實例上處理方法調用並返回結果 * proxy - 在其上調用方法的代理實例 * method - 對應於在代理實例上調用的接口方法的 Method 實例 * args - 包含傳入代理實例上方法調用的參數值的對象數組,若是接口方法不使用參數,則爲 null */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("權限校驗"); //invoke 方法執行後的返回值爲代理類對象 Object result = method.invoke(target, args); System.out.println("日誌分析"); return result; //返回代理類對象 } }
3,測試類,Proxy類中的方法建立動態代理類對象,該方法會返回代理類
public class ProxyTest { /** * 使用JDK動態代理,在原來的方法執行先後執行受權,日誌記錄 * @param args */ public static void main(String[] args) { UserDao userDao = new UserDaoImp(); //不使用代理的狀況下調用方法 userDao.add(); userDao.delete(); //代理用戶 MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userDao); //返回一個指定接口的代理類實例,該接口能夠將方法調用指派到指定的調用處理程序 //返回對象只能是接口UserDao,不能是接口的實現類UserDaoImp,因此說JDK提供的代理只能針對接口作代理 UserDao newProxyInstance = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(),myInvocationHandler); newProxyInstance.add(); newProxyInstance.delete(); System.out.println("--------------------------------"); WorkDao workDao = new WorkDaoImp(); //不使用代理的狀況下調用方法 workDao.work(); workDao.study(); //代理工人 MyInvocationHandler myInvocationHandler2 = new MyInvocationHandler(workDao); WorkDao newProxyInstance2 = (WorkDao) Proxy.newProxyInstance(workDao.getClass().getClassLoader(), workDao.getClass().getInterfaces(), myInvocationHandler2); newProxyInstance2.work(); newProxyInstance2.study(); } }
4, 控制檯輸出 , 在方法執行先後執行了受權和添加日誌的方法,具體方法中業務邏輯能夠根據實際狀況定義
執行了添加的方法 執行了刪除的方法 權限校驗 執行了添加的方法 日誌分析 權限校驗 執行了刪除的方法 日誌分析 -------------------------------- 工做 學習 權限校驗 工做 日誌分析 權限校驗 學習 日誌分析