简单聊聊远程调用的设计模式——动态代理

127 阅读2分钟

静态代理

真实角色与代理角色的关系是一对一的。

  1. 编写含有要调用的方法的接口A
  2. 编写真实角色 需要实现接口A
  3. 编写静态代理角色,需要实现接口A(注意:需要含有真实角色的引用)在重写接口方法时可以引用,与子类调用父类方法super()并添加自己的处理逻辑有异曲同工之妙
  4. 编写测试类:调用代理角色的方法

动态代理(含案例)

用一个“万能的”代理类来代理任何类型的真实角色 不需要给每个真实角色都设置一个代理 是一对多的。

  1. 编写含有要调用的方法的接口A
public interface Subject {
    public abstract boolean rent(int money);
}
  1. 编写真实角色,需要实现接口A
public class RealSubject implements Subject {
    @Override
    public boolean rent(int money){
        System.out.println("租房" + money + "元");
        return true;
    }
}
  1. 编写动态代理角色类,该类是通用的,相当于一个工具类,实现了InvocationHandler接口,并重写invoke()方法,这里是利用了反射技术,获取到真实对象的对应方法执行invoke方法
public class DynamicProxy implements InvocationHandler {
    private Object obj;
    public DynamicProxy(Object obj){
        this.obj = obj;
    }
    public void before(){
        System.out.println("before...");
    }
    public void after(){
        System.out.println("after...");
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        this.before();
        
        Object = result = method.invoke(Obj, args);
        
        this.after();
        return result;
    }
}
  1. 编写测试类:根据真实角色产生一个初步的代理角色handler,再生成一个最终的代理对象,用于执行真实对象的方法
Public class Test {
    public static void main(String[] args){
        Subject realSubject = new RealSubject();
        InvocationHandler handler = new DynamicProxy(realSubject); // 初步代理角色
        Subject subProxy = (Subject) Proxy.newProxyInstance(
            handler.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            handler
        ); // 产生最终代理对象,第一个参数是初步代理对象的类加载器(固定写法),第二个参数是真实角色实现的接口,第三个参数是要转化的初步代理对象
        boolean result = subProxy.rent(3000);
        System.out.println(result ? "ok" : "err");
    }
}