动态代理

代理模式(Proxy)为其他对象提供一种代理以控制对这个对象的访问。使用代理模式创建代理对象,让代理对象控制目标对象的访问(目标对象可以是远程的对象、创建开销大的对象或需要安全控制的对象),并且可以在不改变目标对象的情况下添加一些额外的功能。

代理分为静态代理以及动态代理,在学习完反射后,就可以完成动态代理。

动态对象

要想创建一个代理对象,需要使用Proxy类的newProxyInstance方法。该方法有三个参数:

  • 类加载器
  • Class数组对象,每个元素对应需要实现的各个接口
  • 一个调用处理器Handler

调用处理器是实现了InvocationHandler接口的类的对象。这个接口只有一个方法:

Object invoke(Object proxy, Method method, Object[] args)

无论何时调用代理对象的方法,调用处理器的invoke方法都会被调用,并向其传递Method对象和原调用的参数。之后调用处理器必须确定如何处理这个调用。

下面来写出动态代理,核心代码如下:

class ProxyFactory
{
    public static Object getProxyInstance (Object obj)
    {
        InvocationHandler invocationHandler = (Object proxy, Method method, Object[] args) -> {
            // 调用方法前处理块
            System.out.println("=================method start===================");

            Object o = method.invoke(obj, args);

            // 调用方法后处理块
            System.out.println("=================method end===================");

            return o;
        };

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), invocationHandler);
    }
}

测试代码如下

interface I1
{
    void m1();

    void m2();
}

class C1 implements I1{

    @Override
    public void m1() {
        System.out.println("This is a method1");
    }

    @Override
    public void m2() {
        System.out.println("This is a method2");
    }
}

public class T3 {
    public static void main(String[] args) {
        I1 proxyInstance = (I1) ProxyFactory.getProxyInstance(new C1());
        proxyInstance.m1();
        proxyInstance.m1();
    }
}

输入信息如下:

=================method start===================
This is a method1
=================method end===================
=================method start===================
This is a method2
=================method end===================