浅谈模式 - 代理模式

116 阅读2分钟

真实动作的前面和后面分别做一些行为。真实动作使用委托的方式来调用。

静态代理

public interface Subject {

    void buyTicket();
}
public class SubjectImpl implements Subject {

    @Override
    public void buyTicket() {
        System.out.println("买票");
    }
}
public class SubjectProxy implements Subject {

    private Subject subject;

    public SubjectProxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void buyTicket() {
        this.doBefore();
        subject.buyTicket();
        this.doAfter();
    }

    private void doBefore() {
        System.out.println("doBefore");
    }

    private void doAfter() {
        System.out.println("doAfter");
    }
}

动态代理

public class DynamicSubjectPorxy implements InvocationHandler {

    private Subject subject;

    public DynamicSubjectPorxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.doBefore();
        Object res = method.invoke(subject, args);
        this.doAfter();
        return res;
    }

    private void doBefore() {
        System.out.println("doBefore");
    }

    private void doAfter() {
        System.out.println("doAfter");
    }
}

动态代理的应用会比较多,其实原理挺简单,就是在运行时动态得给某个接口生成一个对象,这个对象实现了目标接口。在JDK中,开发者只需要实现InvocationHandler接口,重写invoke方法。通过 method.invoke(subject, args)方法实现目标方法的调用。那在调用目标方法之前或者调用之后做些什么完全由开发者控制。甚至目标方法都不一定要调用,或者目标方法都不一定有。

如果对于动态代理不熟悉的朋友,务必要亲自动手去写各种案例,否则很难在脑子里形成非常直接的思维。

代理在RPC场景中的应用,比如在Dubbo框架中,服务消费方Consumer只有接口的声明,并没有具体实现,具体实现在服务提供方。那我们就需要给服务消费方的所有接口生成动态代理。当调用服务时,会进入invoke方法。invoke方法中就需要把入参对象等相关信息序列化之后通过TCP方式发送给服务提供方,后续就不在这边细说了。关于Dubbo的服务调用方式相关原理可以参考文档 dubbo服务导出和引入

查看全部 浅谈模式 - 汇总篇