Java动态代理详解

学习spring的时候,涉及到的AOP(面向切面编程),其原理就是动态代理。

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法invoke方法:

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

proxy:  指代我们所代理的那个真实对象

method:  指代的是我们所要调用真实对象的某个方法的Method对象

args:  指代的是调用真实对象某个方法时接受的参数

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:

`public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException`

loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

定义一个代理类

`
class InvokeHandler implements InvocationHandler {

    // 需要代理的对象
    private Object target;

    public InvokeHandler(Object t) {
        target = t;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     * java.lang.reflect.Method, java.lang.Object[])
     * 
     * @proxy:指代我们所代理的那个真实对象
     * 
     * @method:指代的是我们所要调用真实对象的某个方法的Method对象
     * 
     * @args:指代的是调用真实对象某个方法时接受的参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 打印代理对象
        System.out.print(target);
        // 打印代理方法名称
        System.out.print("." + method.getName() + "(");
        // 打印代理方法参数
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                System.out.print(args[i]);
                if (i < args.length - 1) {
                    System.out.print(", ");
                }
            }
        }
        System.out.println(")");
        // 调用代理方法
        return method.invoke(target, args);
    }
}

`

调用代理类实现动态代理

`
    Integer a = 1;
    // 配置第一个代理aProxyInstance,用于代理Integer类型的a。
    InvocationHandler aHandler = new InvokeHandler(a);
    // 其中第一个参数null表示使用默认的类加载器,
    // 第二个参数表明需要代理类实现的接口,
    // 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
    // 第三个参数为调用处理器类
    // 配置第一个代理bProxyInstance,用于代理Integer类型的b。
    Object aProxyInstance = Proxy.newProxyInstance(null, new Class[] { Comparable.class }, aHandler);

    Integer b = 2;
    InvocationHandler bHandler = new InvokeHandler(b);
    Object bProxyInstance = Proxy.newProxyInstance(null, new Class[] { Comparable.class }, bHandler);

    Comparable aComparable = (Comparable) aProxyInstance;
    Comparable bComparable = (Comparable) bProxyInstance;
    System.out.println(aComparable.compareTo(b));
    System.out.println(bComparable.compareTo(a));
`

控制台打印

1.compareTo(2)
-1
2.compareTo(1)
1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值