静态代理、动态代理

53 阅读2分钟

代理模式

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

静态代理

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

首先,实现接口:

public interface SayHello {
    void sayHello();
}

其次,实现被代理对象:

public class JackSayHello implements SayHello {
    @Override
    public void sayHello() {
        System.out.println("hello jack");
    }
}

最后,实现静态代理类:

public class JackSayHelloProxy implements SayHello {
    private JackSayHello jackSayHello; // 保存被代理对象

    /**
     * 构造函数,入参为被代理对象
     *
     * @param jackSayHello 被代理对象
     */
    JackSayHelloProxy(JackSayHello jackSayHello) {
        this.jackSayHello = jackSayHello;
    }

    @Override
    public void sayHello() {
        System.out.println("before");
        jackSayHello.sayHello();
        System.out.println("after");
    }
}

调用方式:

public class Main {
    public static void main(String[] args) {
        JackSayHello jackSayHello = new JackSayHello();
        JackSayHelloProxy jackSayHelloProxy = new JackSayHelloProxy(jackSayHello);
        jackSayHelloProxy.sayHello();
    }
}

但是静态对象的缺点很明显,一次只能代理一个对象

动态代理

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

image.png

image.png

首先实现代理处理器,用于拦截代理对象的方法:

/**
 * 代理处理器
 */
public class ProxyHandler implements InvocationHandler {
    // 被代理的接口
    private SayHello sayHello;

    ProxyHandler(SayHello sayHello) {
        this.sayHello = sayHello;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 可以通过识别 method.getName 对接口中不同函数进行区别处理
        if ("sayHello".equals(method.getName())) {
            System.out.println("before sayHello");
            Object result = method.invoke(sayHello, args);
            System.out.println("after sayHello");
            return result;
        }
        return null;
    }
}

然后实现被代理接口和被代理对象,被代理对象可以有多个:

public interface SayHello {
    void sayHello();
}
public class JackSayHello implements SayHello {
    @Override
    public void sayHello() {
        System.out.println("hello jack");
    }
}
public class TomSayHello implements SayHello {
    @Override
    public void sayHello() {
        System.out.println("hello tom");
    }
}

调用方法:

public class Main {
    public static void main(String[] args) {
        // 代理Jack
        // 1.创建被代理对象
        SayHello realImpl = new JackSayHello();
        // 2.创建代理处理器
        ProxyHandler proxyHandler = new ProxyHandler(realImpl);
        // 3.动态生成代理对象
        SayHello proxyInstance = (SayHello) Proxy.newProxyInstance(realImpl.getClass().getClassLoader(), realImpl.getClass().getInterfaces(), proxyHandler);
        // 4.客户端通过代理对象调用方法,将自动被代理处理器的invoke方法拦截
        proxyInstance.sayHello();
        
        // 代理Tom
        realImpl = new TomSayHello();
        proxyHandler = new ProxyHandler(realImpl);
        proxyInstance = (SayHello) Proxy.newProxyInstance(realImpl.getClass().getClassLoader(), realImpl.getClass().getInterfaces(), proxyHandler);
        proxyInstance.sayHello();
    }
}

结果:

before sayHello
hello jack
after sayHello
before sayHello
hello tom
after sayHello