Spring動態代理

1.  動態代理

動態代理:在程序運行時,運用反射機制動態創建而成。

1、 動態代理和靜態代理的角色是一樣的。

2、 動態代理的代理類是動態生成的。

3、 分爲兩類一類基於接口動態代理和基於類的動態代理。

a)    基於接口動態代理---jdk動態代理

                i.         Java動態代理使用Proxy類和InvocationHandler接口。

               ii.         使用Proxy類做代理的時候,必須有InvocationHandler對象。

public static Object newProxyInstance(ClassLoader loader,

                                      Class<?>[] interfaces,

                                      InvocationHandler h)

                               throws IllegalArgumentException

 

loader - 定義代理類的類加載器

interfaces - 代理類要實現的接口列表

h - 指派方法調用的調用處理程序

Object: 因爲不能確定要代理的對象是什麼類型,所以要返回類的祖先!

是誰創建的動態代理?

InvocationHandler:

invoke(Object proxy, Method method, Object[] args)

Object invoke(Object proxy,

              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方法不一樣!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章