目錄html
接口:IUserDao.java public interface IUserDao { void save(); } 目標對象類:UserDao.java public class UserDao implements IUserDao { public void save() { System.out.println("----已經保存數據!----"); } } 代理對象:UserDaoProxy.java public class UserDaoProxy implements IUserDao{ //接收保存目標對象 private IUserDao target; public UserDaoProxy(IUserDao target){ this.target=target; } public void save() { System.out.println("開始事務..."); target.save();//執行目標對象的方法 System.out.println("提交事務..."); } } 測試類:App.java public class App { public static void main(String[] args) { //目標對象 UserDao target = new UserDao(); //代理對象,把目標對象傳給代理對象,創建代理關係 UserDaoProxy proxy = new UserDaoProxy(target); proxy.save();//執行的是代理的方法 } }
代理類所在包:java.lang.reflect.Proxy
JDK實現代理只須要使用newProxyInstance方法,可是該方法須要接收三個參數,完整的寫法是:java
static Object newProxyInstance(ClassLoader loader, Class [] interfaces, InvocationHandler handler) 注意該方法是在Proxy類中是靜態方法,且接收的三個參數依次爲:
java.lang.reflect.InvocationHandler:這是調用處理器接口,它自定義了一個 invoke 方法,用於集中處理在動態代理類對象上的方法調用,一般在該方法中實現對委託類的代理訪問。編程
// 該方法負責集中處理動態代理類上的全部方法調用。第一個參數既是代理類實例,第二個參數是被調用的方法對象 // 第三個方法是調用參數。 Object invoke(Object proxy, Method method, Object[] args)
接口類IUserDao.java以及接口實現類UserDao是同樣的.在這個基礎上,增長一個代理工廠類(ProxyFactory.java),將代理類寫在這個地方,而後在測試類中先創建目標對象和代理對象的聯繫,而後使用代理對象中的同名方法segmentfault
代理工廠類:ProxyFactory.java /** * 建立動態代理對象 * 動態代理不須要實現接口,可是須要指定接口類型 */ public class ProxyFactory{ //維護一個目標對象 private Object target; public ProxyFactory(Object target){ this.target=target; } //給目標對象生成代理對象 public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始事務2"); //執行目標對象方法 Object returnValue = method.invoke(target, args); System.out.println("提交事務2"); return returnValue; } } ); } } 測試類:App.java /** * 測試類 */ public class App { public static void main(String[] args) { // 目標對象 IUserDao target = new UserDao(); // 【原始的類型 class cn.itcast.b_dynamic.UserDao】 System.out.println(target.getClass()); // 給目標對象,建立代理對象 IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance(); // class $Proxy0 內存中動態生成的代理對象 System.out.println(proxy.getClass()); // 執行方法 【代理對象】 proxy.save(); } }
@Override public Object invoke(Object instance, Method method, Object[] args) throws Throwable { String clazz = manager.getClass().getName(); String methodName = method.getName(); if (args==null) { try { return method.invoke(manager, args); } catch (InvocationTargetException e) { throw e.getCause();// 關鍵在於要拋出真實的異常,若是多層次代理調用,則須要循環處理 } } ... }
public class PrivilegeValidationProxy<T extends MetaBean> implements InvocationHandler { protected MetaManager<T> manager; public PrivilegeValidationProxy(MetaManager<T> manager) { super(); this.manager = manager; } @Override public Object invoke(Object instance, Method method, Object[] args) throws Throwable { ... // 驗證權限 valid(); method.invoke(manager, args); } } public class DatasetManager extends MetaManager<DatasetBean> implements DatasetManagerI { public static DatasetManagerI instance = newInstance(); public static DatasetManagerI getInstance() { return instance; } public static DatasetManagerI newInstance() { DatasetManager manager = new DatasetManager(); return (DatasetManagerI) Proxy.newProxyInstance(manager.getClass().getClassLoader(), new Class[] { DatasetManagerI.class }, new PrivilegeValidationProxy<DatasetBean>(manager)); } }
目標對象類:UserDao.java /** * 目標對象,沒有實現任何接口 */ public class UserDao { public void save() { System.out.println("----已經保存數據!----"); } } Cglib代理工廠:ProxyFactory.java /** * Cglib子類代理工廠 * 對UserDao在內存中動態構建一個子類對象 */ public class ProxyFactory implements MethodInterceptor{ //維護目標對象 private Object target; public ProxyFactory(Object target) { this.target = target; } //給目標對象建立一個代理對象 public Object getProxyInstance(){ //1.工具類 Enhancer en = new Enhancer(); //2.設置父類 en.setSuperclass(target.getClass()); //3.設置回調函數 en.setCallback(this); //4.建立子類(代理對象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("開始事務..."); //執行目標對象的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事務..."); return returnValue; } } 測試類: /** * 測試類 */ public class App { @Test public void test(){ //目標對象 UserDao target = new UserDao(); //代理對象 UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance(); //執行代理對象的方法 proxy.save(); } }
將日誌記錄,性能統計,安全控制,事務處理,異常處理等代碼從業務邏輯代碼中劃分出來,經過對這些行爲的分離,咱們但願能夠將它們獨立到非業務邏輯的方法中,進而改變這些行爲的時候不影響業務邏輯的代碼---解耦。
**在Spring的AOP編程中:設計模式