動態(tài)代理

動態(tài)代理和代理模式有些相似,都是對某個類中的某些方法進行監(jiān)聽,代理模式在這里不多說,下面概括一下動態(tài)代理,以下概括完全是基于個人理解總結的:
動態(tài)代理:在不改變原有類實現(xiàn)的基礎上,通過實現(xiàn)類的接口,對類實現(xiàn)的接口方法的調(diào)用進行監(jiān)聽,實現(xiàn)接口方法調(diào)用前后。0

動態(tài)代理實現(xiàn)方法:

  1. 定義被代理類的接口方法
  2. 創(chuàng)建被代理類并實現(xiàn)接口方法
  3. 創(chuàng)建代理類
  4. 添加代理

動態(tài)代理的實現(xiàn)

下面我們以對User對象的添加和查找進行代理為例。
User實體對象如下:

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

定義被代理類的接口方法

創(chuàng)建被代理類中代理方法的接口。

public interface IUserControl {
    
    public void addUser(User user);
    
    public User getUser(int index);
}

創(chuàng)建被代理類并實現(xiàn)接口方法

被代理的對象,一定要實現(xiàn)上面定義的接口

public class UserControl implements IUserControl {
    
    private User user;
    
    @Override
    public void addUser(User user) {
        this.user = user;
    }

    @Override
    public User getUser(int index) {
        return this.user;
    }
    
    public void delete() {}
}

在上面實體中,有兩種方法的實現(xiàn),一種是接口方法實現(xiàn)(必須有),一種是實體自己的方法(可有可無)。

創(chuàng)建代理類

代理類代碼很少,也非常簡單,先上代碼,然后在說明:

public class UserProxy implements InvocationHandler {
    private UserControl control;
    private IProxyListener listener;

    public UserProxy(UserControl control, IProxyListener listener) {
        this.control = control;
        this.listener = listener;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj;
        listener.methoBefor();
        obj = method.invoke(control,args);
        listener.methodAfter();
        return obj;
    }
}

代碼雖然不是很多,但是這里很關鍵,不了解的人看了一定會有很多疑問,下面介紹一下這部分代碼。
InvocationHandler 接口
每一個動態(tài)代理類都必須要實現(xiàn)InvocationHandler這個接口,并且每個代理類的實例都關聯(lián)到了一個handler,當我們通過代理對象調(diào)用一個方法的時候,這個方法的調(diào)用就會被轉發(fā)為由InvocationHandler這個接口的 invoke 方法來進行調(diào)用。

看到這里怎么又出來個invoke 方法,下面我們在看看invoke 方法。

invoke 方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable

我們看到這個方法一共接受三個參數(shù),那么這三個參數(shù)分別代表什么:

proxy:  指代我們所代理的那個真實對象
method:  指代的是我們所要調(diào)用真實對象的某個方法的Method對象
args:  指代的是調(diào)用真實對象某個方法時接受的參數(shù)

看到這里知道上面代碼中為什么obj = method.invoke(control,args);這樣寫了吧,其實不難理解invoke 方法是通過InvocationHandler接口進行調(diào)用的。

添加代理

public class ProxyMain {
    public static void main(String[] args) {
        UserControl control = new UserControl();
        UserProxy proxy = new UserProxy(control, new IProxyListener() {
            @Override
            public void methoBefor() {
                System.out.println("method beford");
            }

            @Override
            public void methodAfter() {
                System.out.println("method after");
            }
        });

        IUserControl iUserControl = (IUserControl) Proxy.newProxyInstance(proxy.getClass().getClassLoader(),control.getClass().getInterfaces(),proxy);
        iUserControl.addUser(new User("hello",23));
        User user = iUserControl.getUser(0);
        System.out.println("user:" + user.getName());
    }
}

上面代碼依然不是很多,其實關鍵的一行代碼是:

IUserControl iUserControl = (IUserControl) Proxy.newProxyInstance(
        proxy.getClass().getClassLoader(),control.getClass().getInterfaces(),proxy);

看到這突然出來了一個Proxy類,Proxy這個類的作用就是用來動態(tài)創(chuàng)建一個代理對象的類的,Proxy 類有好幾個方法,我們常用的就是newProxyInstance方法,通過這個方法名也能知道這個方法是干什么的,這個方法作用是創(chuàng)建一個代理實例的。這個方法有三個參數(shù),下面說明一下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

loader: 一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行加載
interfaces: 被代理對象實現(xiàn)的接口數(shù)組
h: 一個InvocationHandler對象,實現(xiàn)InvocationHandler接口的代理對象

以上就是動態(tài)代理的實現(xiàn)過程,很簡單吧?。。?/p>

如果上述有錯誤請指出,共同學習,共同進步。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容