JAVA 代理模式(Proxy)的原理和实现

来源:互联网 发布:windows sdk 版本8.1 编辑:程序博客网 时间:2024/05/29 03:17

代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

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

抽象角色:声明真实对象和代理对象的共同接口;

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

代理方法:

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();    }}

结果显示:
这里写图片描述
这里写图片描述

原创粉丝点击