动态代理

来源:互联网 发布:淘宝拍摄基地 编辑:程序博客网 时间:2024/06/04 18:53

 动态代理是在代理模式基础上发展的,它不是对单一类型进行代理,而是可以对任意一个实现了接口的类的对象进行代理。动态代理可以实现拦截对真实对象的访问。

1. 动态代理的实现
 动态代理的实现由两种方式,一种是通过JDK提供的Proxy类来实现。这种方式要求被代理类必须实现接口。简单讲,就是只能为接口做代理。

 第二种是通过cglib来实现(这个是spring框架中的方法)。

2. 代理Proxy类
 Proxy提供用于创建动态代理类和实例的静态方法。在这个类中有个静态方法:static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h),它将返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。下面来介绍这个方法的参数。
第一个参数loader:
loader是一个类加载器,在使用这个方法的时候,我们要传递的应该是这个被代理类的类加载器。我们如何获取类加载器呢?首先得到这个类的Class对象,在Class对象中提供了一种方法 getClassLoader()能够获取到这个类的类加载器。

第二个参数interfaces:
interfaces是一个Class[]数组,我们要传递的是这个被代理类中的所有的interface接口的Class对象。我们如何获取接口的Class数组对象呢?首先我们得到这个类的Class对象,然后在Class对象中提供了一种方法getInterfaces(),它返回的是Class[],就代表所实现接口的所有Class对象。

第三个参数h:
它的类型是InvocationHandler,这是一个接口。InvocationHandler 是代理实例的调用处理程序实现的接口。

3. InvocationHandler接口
 在InvocationHandler中只有个方法invok,现在我们来看看这个方法的详细分析。
public Object invoke(Object proxy, Method method, Object[] args),这个方法有三个参数,参数proxy就是代理对象。参数method就是调用方法,参数args就是调用方法的参数。而返回值就是真实行为执行后返回的结果,会传递给代理对象调用的方法。

4. 注意事项
 <1>Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。

 <2>由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。
5. 动态代理实例
被代理实现的接口:

//定以一类男人,会拍照public interface KindMan {    public void photo();}

被代理对象(陈冠希):

//陈冠希实现了这类人,具体化了拍照的方法public class Cgx implements KindMan{    public void photo() {        System.out.println("陈冠希拍照。。。。");    }}

动态代理:

public class DproxyDemo {    public static void main(String[] args) {        //做一个陈冠希代理。        final KindMan man = new Cgx();        KindMan manProxy = (KindMan) Proxy.newProxyInstance(            //第一个参数是类加载器            man.getClass().getClassLoader(),             //第二个参数是实现接口的Class[]数组            man.getClass().getInterfaces(),                //第三个参数是一个处理器。这边以匿名的形式作为参数。                new InvocationHandler() {                    public Object invoke(Object proxy, Method method, Object[] args)                            throws Throwable {                        return method.invoke(man, args);                    }                });        manProxy.photo();    }}

测试的结果为:
陈冠希拍照。。。。

原创粉丝点击