1. 動態代理
動態代理:在程序運行時,運用反射機制動態創建而成。
1、 動態代理和靜態代理的角色是一樣的。
2、 動態代理的代理類是動態生成的。
3、 分爲兩類一類基於接口動態代理和基於類的動態代理。
a) 基於接口動態代理---jdk動態代理
i. Java動態代理使用Proxy類和InvocationHandler接口。
ii. 使用Proxy類做代理的時候,必須有InvocationHandler對象。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, throws IllegalArgumentException
loader - 定義代理類的類加載器 interfaces - 代理類要實現的接口列表 h - 指派方法調用的調用處理程序 Object: 因爲不能確定要代理的對象是什麼類型,所以要返回類的祖先! 是誰創建的動態代理? InvocationHandler: invoke Method method, Object[] args) throws Throwable proxy - 在其上調用方法的代理實例
method - 對應於在代理實例上調用的接口方法的 Method 實例。Method 對象的聲明類將是在其中聲明方法的接口,該接口可以是代理類賴以繼承方法的代理接口的超接口。
args - 包含傳入代理實例上方法調用的參數值的對象數組,如果接口方法不使用參數,則爲 null。基本類型的參數被包裝在適當基本包裝器類(如 java.lang.Integer 或 java.lang.Boolean)的實例中。 利用靜態代理中的例子來解釋: Proxy: 中介UserProxy Method:rent()方法 Args:參數:null |
b) 基於類的動態代理---cglib
i. 對指定的目標類生成一個子類,並覆蓋其中方法實現增強,但因爲採用的是繼承,所以不能對final修飾的類進行代理。
案例:使用動態代理,在每個方法執行前,添加一句話【方法被執行了】。
1、在UserDao接口中層創建四個方法:CRUD
2、在UserDaoImpl類中實現四個方法:CRUD
3、創建一個代理類實現InvocationHandler接口中的invoke方法。
動態代理實現步驟:
1、 創建一個類來實現InvocationHandler接口。實現invoke方法()
a) Invoke方法中就是具體的你要實現的功能!
i. 輸出我們的“方法被執行了!”
2、 在該接口中創建動態代理。Proxy. newProxyInstance(參數1,參數2,參數3);
3、 測試!
代碼:
public interface UserDao { void add(); void delete(); void update(); void search(); String show(); }
public class UserDaoImpl implements UserDao {
@Override public void add() { System.out.println("添加用戶"); } @Override public void delete() { System.out.println("刪除用戶"); }
@Override public void update() { System.out.println("更新用戶"); }
@Override public void search() { System.out.println("查詢用戶"); } @Override public String show() { return "show"; } }
public class UserDaoProxy implements InvocationHandler { // 聲明要代理的對象 private Object object;
public Object getObject() { return object; }
// 給代理對象賦值 public void setObject(Object object) { this.object = object; }
// 如何創建一個代理對象?使用Proxy類來創建 public Object getProxy() { // 第一個參數是類加載器,第二個參數是代理對象的接口,第三個是InvocationHandler 對象 return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this); }
/** * proxy 代理的對象 method 代理對象的方法 args 參數數組 */
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { txStart(); // obj:被代理的對象!args:參數數組,說白了。 method.invoke(object, args) 就是執行真是代理對象的方法。 Object obj = method.invoke(object, args); System.out.println(obj+"=========="); txClose(); return obj; }
public void txStart() { System.out.println("開啓事務!"); }
public void txClose() { System.out.println("關閉事務!"); }
} 測試: public class Test { public static void main(String[] args) { // 創建代理對象 UserDaoProxy u = new UserDaoProxy(); // 創建代理對象 ,說明你要代理的那個類 UserDao ud = new UserDaoImpl(); u.setObject(ud); // 得到代理對象! UserDao userDao = (UserDao) u.getProxy(); // 代理類的方法被執行的時候,則會調用InvocationHandler中的invoke方法。 userDao.add(); userDao.delete(); userDao.search(); userDao.show();
} } 能否將租房改成動態代理。 注意:InvocationHandler 的invoke、方法 和 method.invoke方法不一樣! |