再说Java动态代理

一、Java动态代理的实现方式
Java动态代理有两种方式实现
1、首先得到代理类,然后创建代理实例


InvocationHandler handler = new InvocationHandlerImpl(..);   

// 1、得到指定接口代理类的Class
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });   

// 2、得到代理类的构造函数  
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });   

// 3、通过构造函数对象创建动态代理类实例  
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler }); 

2、一步到位,直接获取代理实例

// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发  
InvocationHandler handler = new InvocationHandlerImpl(..);   

// 通过 Proxy 直接创建动态代理类实例  
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,   
     new Class[] { Interface.class },   
     handler ); 

其实两种方式的本质一样,只是第二种是对第一种的一种封装罢了。

原理:我们指定这种实现是得到指定接口的代理类,然后我们的目标类也是实现这个接口,所以它必须针对接口而言。

实质:得到一个实现指定接口的类的class字节码

举个例子:

Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), new Class[] { Collection.class}); 
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class }); 
Collection Proxy = (Collection) constructor.newInstance(new InvocationHandler[] { handler }); 

我们可以这样理解:
1、Proxy.getProxyClass(Collection.class.getClassLoader(), new Class[] { Collection.class})得到下面类Proxy0的字节码。
2、clazz.getConstructor(new Class[] { InvocationHandler.class })得到类Proxy0的构造函数
3、constructor.newInstance(new InvocationHandler[] { handler })创建了类Proxy0的实例。

下面这个类Proxy0类的字节码在调用Proxy.getProxyClass()的时候会生成,下面将它以java代码的形式展现,实质在生成的时候,内部的实现是直接得到它的class文件,然后将它进行加载得到对应的Class。

import java.lang.reflect.InvocationHandler;
import java.util.Collection;
import java.util.Iterator;

public class Proxy0 implements Collection {
    private InvocationHandler mHandler;

    public Proxy0(InvocationHandler handler) {
        mHandler = handler;
    }

    @Override
    public int size() {
        int result = 0;
        try {
            result = (int) mHandler.invoke(this, Collection.class.getMethod("size", null), null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean isEmpty() {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("isEmpty", null), null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean contains(Object o) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("contains", Object.class), new Object[]{o});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public Iterator iterator() {
        Iterator result = null;
        try {
            result = (Iterator) mHandler.invoke(this, Collection.class.getMethod("iterator", null), null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public Object[] toArray() {
        Object[] result = null;
        try {
            result = (Object[]) mHandler.invoke(this, Collection.class.getMethod("toArray", null), null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public Object[] toArray(Object[] a) {
        Object[] result = null;
        try {
            result = (Object[]) mHandler.invoke(this, Collection.class.getMethod("toArray", Object[].class), new Object[]{a});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean add(Object o) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("add", Object.class), new Object[]{o});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean remove(Object o) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("remove", Object.class), new Object[]{o});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean containsAll(Collection c) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("containsAll", Collection.class), new Collection[]{c});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean addAll(Collection c) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("addAll", Collection.class), new Collection[]{c});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean removeAll(Collection c) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("removeAll", Collection.class), new Collection[]{c});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean retainAll(Collection c) {
        boolean result = false;
        try {
            result = (boolean) mHandler.invoke(this, Collection.class.getMethod("retainAll", Collection.class), new Collection[]{c});
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public void clear() {
        try {
            mHandler.invoke(this, Collection.class.getMethod("clear", null), null);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

}

可以看到,我们在调用代理类Proxy0对应的方法的时候,实质调用的是InvocationHandler的invoke方法,也就是代理类的所有方法都会走InvocationHandler的invoke方法这个通道,而InvocationHandler实例是我们创建代理类Proxy0的时候传进去的,具体实现是我们自己来处理,所以我们在invoke方法里面不仅可以调用目代理标类实例方法而且可以添加自己的业务处理。

下面举个例子:

public class ProxyTest {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
        Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), new Class[] { Collection.class}); 
        Constructor constructor = clazz.getConstructor(InvocationHandler.class);

        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new ArrayList(), new Callable() {
            @Override
            public void beforeCall() {
                System.out.println("beforeCall");

            }

            @Override
            public void afterCall() {
                System.out.println("afterCall");

            }

        });
        Collection proxy = (Collection) constructor.newInstance(new InvocationHandler[] { myInvocationHandler });


        System.out.println(proxy.add("Hello"));

        }

}

class MyInvocationHandler<T> implements InvocationHandler {
    private T mTarget;
    private Callable mCallable;
    public MyInvocationHandler(T t, Callable c) {
        mTarget = t;
        mCallable = c;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        mCallable.beforeCall();
        result = method.invoke(mTarget, args);
        mCallable.afterCall();
        return result;
    }
}


interface Callable {
    void beforeCall();
    void afterCall();
}

上面代理思路可以用如下类图表示。

这里写图片描述

ArrayList是目标类,Proxy0是ArrayList的代理类。

调用过程如下:

这里写图片描述

调用Proxy0中的方法都会对应调用InvocationHandler的invoke方法,在invoke方法中调用目标类ArrayList的对应方法和额外操作。

为了使整个代理思想更加清晰,我们下面进行一下封装。

public class ProxyClass implements InvocationHandler {  
    private Object mTarget;  
    private Callable mCallable;

    // 对指定对象绑定一个代理对象
    public Object bind(Object target, Callable callable) {  
        this.mTarget = target;  
        this.mCallable = callable;
        //取得代理对象  
        return Proxy.newProxyInstance(mTarget.getClass().getClassLoader(),  
                target.getClass().getInterfaces(), this); 
    }  

    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result=null;  
        callable.beforeCall();
        //执行方法  
        result=method.invoke(target, args);  
        callable.afterCall();
        return result;  
    }  
}  

interface Callable {
    void beforeCall();
    void afterCall();
}
public class TestProxy {  

    public static void main(String[] args) {  
        // 创建代理对象
        ProxyClass proxy = new ProxyClass();  
        // 为代理指定目标对象和额外处理回调
        Collection collectionProxy = (Collection) proxy.bind(new ArrayList(), new Callable() {
            @Override
            public void beforeCall() {
                System.out.println("beforeCall");

            }

            @Override
            public void afterCall() {
                System.out.println("afterCall");

            }

        });  
        // 使用代理来调用目标类的函数
        collectionProxy.add("Hello");
    }  

}  

欢迎关注微信公众号:DroidMind
精品内容独家发布平台


呈现与博客不一样的技术干货

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值