代理模式

代理模式简介

  • 原理图
  • 简介
    代理模式是23个经典模式的一种,又称委托模式。为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问,
    外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
    代理对象中可以添加监控和审查处理

静态代理

代理对象持有目标对象的句柄
所有调用目标对象的方法,都调用代理对象的方法
对每个方法,需要静态编码(理解简单,但需要增加新功能时代码繁琐)

public interface Subject {
    public void request();
}

public class SubjectImpl implements Subject {
    @Override
    public void request() {
        System.out.println("i am dealing the request");
    }
}

public class StaticProxy implements Subject {
    //实际目标对象
    private Subject subject;
    public StaticProxy(Subject subject) {
        this.subject = subject;
    }
    @Override
    public void request() {
        System.out.println("preprocess");
        subject.request();
        System.out.println("postprocess");
    }
}

public class StaticProxyDemo {
    public static void main(String[] args) {
        //创建实际对象
        SubjectImpl subjectImpl = new SubjectImpl();
        //把实际对象封装到代理对象中
        StaticProxy staticProxy = new StaticProxy(subjectImpl);
        staticProxy.request();
    }
}

动态代理

对目标对象的方法每次调用,进行动态拦截

  • 代理处理器
    持有目标对象的句柄
    实现InvocationHandler接口
    • 实现invoke方法
    • 所有的代理对象方法调用,都会转发到invoke方法来
    • invoke的形参method,就是指代理对象方法的调用
    • 在invoke内部,可以根据method,使用目标对象不同的方法来响应请求
  • 代理对象
    根据给定的接口,由Proxy类自动生成的对象
    类型com.sun.proxy.$Proxy(),继承自java.lang.reflect.Proxy
    通常和目标对象实现同样的接口(可另实现其他的接口)
    实现多个接口
    • 接口的排序非常重要
    • 当多个接口里面由方法同名,则默认以第一个接口的方法调用
public interface Subject {
    public void request();
}

public class SubjectImpl implements Subject {
    @Override
    public void request() {
        System.out.println("i am dealing the request");
    }
}

public class ProxyHandler implements InvocationHandler {
    private Subject subject;
    public ProxyHandler(Subject subject) {
        this.subject = subject;
    }
    //此方法在代理对象调用任何一个方法时都会被调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println(proxy.getClass().getName());
        //定义预处理的工作,也可以根据method的不同进行不同的预处理工作
        System.out.println("---------before-------");
        Object result = method.invoke(subject, args);
        System.out.println("--------after---------");
        return result;
    }
}

public class DynamicProxyDemo {
    public static void main(String[] args) {
        //创建目标对象
        SubjectImpl subjectImpl = new SubjectImpl();
        //创建调用处理器对象
        ProxyHandler proxyHandler = new ProxyHandler(subjectImpl);
        //动态生成代理对象
        Subject proxySubject =(Subject) Proxy.newProxyInstance(SubjectImpl.class.getClassLoader(),SubjectImpl.class.getInterfaces(),proxyHandler);
        //客户端通过代理对象调用方法,本次调用将自动被代理处理器的invoke方法接收
        proxySubject.request();
        System.out.println(proxySubject.getClass().getName());
    }
}

David Wheeler(函数发明者):All problems in computer science can be solved by another level of indirection

posted @ 2021-01-28 14:32  liuaaaaaa  阅读(39)  评论(0)    收藏  举报