InvocationHandler动态代理 与 面向切面编程

先看一个常规案例

接口类:

public interface MyInterface {
    int add(int a, int b);
}

实现类:

public class MyInterfaceImpl implements MyInterface {
    @Override
    public int add(int a, int b) {
        System.out.println("calculating...");
        return  a + b;
    }
}

使用InvocationHandler

public class MyHandler implements InvocationHandler {
    private MyInterface myInterface;

    public MyHandler(MyInterface interface) {
        this.myInterface = interface;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before...");
        Object invoke = method.invoke(myInterface, args);
        System.out.println("after...");
        return invoke;
    }

    public MyInterface getProxy() {
        return (MyInterface) Proxy.newProxyInstance(myInterface.getClass().getClassLoader(),
                myInterface.getClass().getInterfaces(), this);
    }
}
public class Test {
    public static void main(String[] args) {
        //要代理的真实对象
        MyInterface addInterface = new MyInterfaceImpl();
        //代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法
        InvocationHandler handler = new MyHandler(addInterface);
        /**
         * 通过Proxy类的newProxyInstance方法创建代理对象,我们来看下方法中的参数
         * 第一个参数:addInterface.getClass().getClassLoader(),使用handler对象的classloader对象来加载我们的代理对象
         * 第二个参数:addInterface.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
         * 第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
         */
        MyInterface proxy = (MyInterface)Proxy.newProxyInstance(handler.getClass().getClassLoader(), addInterface.getClass().getInterfaces(), handler);
        System.out.println(proxy.add(1, 2).toString());
    }
}

before...
calculating...
after...
3

注意:

  1. 在InvocationHandler接口中只有一个方法 invoke,在这个方法中反射调用 Object invoke = method.invoke(myInterface, args); 就是myInterface接口中方法的实现,在这个方法调用前后,可以加入别的操作,这个操作视具体业务而定(例如:保存数据,判断登录等等),而这个操作就被视为面向切面编程中的切面。
  2. 可以定义getProxy方法,在方法中里面调用Proxy.newProxyInstance 获取一个代理对象,
    如果不加这个方法,需要在对应类中使用
(MyInterface)Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
                new class[]{MyInterface.class}, new MyHandler(this));

来获取一个MyInterface对象

  1. 上面我们只讲解了Proxy中的newProxyInstance(生成代理类的方法),但是它还有其它的几个方法,我们下面就介绍一下:
  • getInvocationHandler:返回指定代理实例的调用处理程序
  • getProxyClass:给定类加载器和接口数组的代理类的java.lang.Class对象。
  • isProxyClass:当且仅当使用getProxyClass方法或newProxyInstance方法将指定的类动态生成为代理类时,才返回true。
  • newProxyInstance:返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。

你可能感兴趣的:(InvocationHandler动态代理 与 面向切面编程)