JAVA 代理模式(Proxy)的原理和實現

代理模式
代理模式的作用是:爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

代理模式一般涉及到的角色有:

抽象角色:聲明真實對象和代理對象的共同接口;

代理角色:代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當於對真實對象進行封裝。

真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。

代理方法:

Proxy.newProxyInstance(ProxyDemo2.class.getClassLoader(),//我們需要一個代理類的classloader
                                                 new Class[]{List.class}, //一個被代理的class接口
                                                 new MyInvocation());//一個InvocationHandler的實現類
//我們在InvocationHandler這個類中通過method方法進行攔截很功能增強

public Object invoke(Object proxy, Method method, Object[] args)throws 
Throwable{
        System.out.println("馬上執行"+method.getName());
        return method.invoke(list, args);
    }

所被代理的角色,它能被代理角色所控制,能夠將真實角色調用方法前進行攔截增強

舉一個例子:
我們將List類進行代理

package cn.hncu.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class ProxyDemo2 {
    @Test
    public void demo2(){
        Object ProxiedObj=Proxy.newProxyInstance(ProxyDemo2.class.getClassLoader(), 
                                                 new Class[]{List.class}, 
                                                 new MyInvocation());
        List list =(List) ProxiedObj;//我們要用代理實現類賦值,自己本身類是無法實現代理的
        list.add(2);
        System.out.println(list.get(0));
    }
}
class MyInvocation implements InvocationHandler{
    List list =new ArrayList();
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("馬上執行"+method.getName());
        return method.invoke(list, args);
    }

}

那麼此時List類被代理後,它所調用的方法會被ProxyDemo2類進行攔截,通過invoke在調用每個方法時會輸出:馬上執行+method.getName
這裏寫圖片描述

那麼我們通過proxy代理也可以進行類的判定來進行多個類的方法調用和增強攔截

需求:
一個Animal的接口和dog實現類 有run()方法 通過該方法輸出:System.out.println(“dog”+name+”is running”);

package cn.hncu.proxyUtils;

public interface Animal {
    public void run();
}
package cn.hncu.proxyUtils;

public class dog implements Animal{
    private String name;

    public dog(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println("dog"+name+"is running");
    }

}

一個iperson的接口和person的實現類,有一個sayHi方法,通過該方法輸出:System.out.println(“我叫”+name);

package cn.hncu.proxyUtils;

public interface IPerson {
    public void sayHi();
}
package cn.hncu.proxyUtils;

public class person implements IPerson{
    private String name;
    public person(String name) {
        this.name = name;
    }
    @Override
    public void sayHi() {
        System.out.println("我叫"+name);

    }

}

那麼我們需要寫一個proxy的utils工具類

package cn.hncu.proxyUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtils implements InvocationHandler{
    private Object srcObj=null;

    public ProxyUtils(Object srcObj) {
        this.srcObj = srcObj;
    }

    public static Object getProxy(Object srcObj) {
        Object proxObject = Proxy.newProxyInstance(ProxyUtils.class.getClassLoader(),
                                                   srcObj.getClass().getInterfaces(),//獲取被代理類的接口
                                                   new ProxyUtils(srcObj));//通過構造傳參將外部的類傳進來
        return proxObject;//將代理類返回出去

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("攔截方法:");//在這裏進行攔截
        Object res=method.invoke(srcObj, args);
        return res;
    }

}

package cn.hncu.proxyUtils;

import org.junit.Test;

public class testProxy {
    @Test
    public void t(){
        dog dog = new dog("aa");
        Animal d = (Animal) ProxyUtils.getProxy(dog);
        d.run();
    }
    @Test
    public void t2(){
        person p =new person("bb");
        IPerson p1=(IPerson) ProxyUtils.getProxy(p);
        p1.sayHi();
    }
}

結果顯示:
這裏寫圖片描述
這裏寫圖片描述

發佈了105 篇原創文章 · 獲贊 10 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章