Java代理(三) JDK动态代理

来源:互联网 发布:手机淘宝怎么清除缓存 编辑:程序博客网 时间:2024/06/06 03:20

定义

动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。

实现方式


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

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

java.lang.reflect.InvocationHandler#invoke
//proxy:指我们所代理的那个真实对象//method:真实对象调用的方法//args:传入方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
可以看出,现在还不知道代理类对象是什么,这用到了另一个类:java.lang.reflect.Proxy
Proxy类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法

//返回 动态的代理对象
//loader: 加载代理对象的ClassLoader//interfaces:一个Interface对象的数组,代理类实现的这些接口列表//h:关联到的InvocationHandler对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

Java代码案例:
package com.tlk.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * Created by tanlk on 2017/8/16 17:32. */public class JDKDynamicProxyTest {    interface Subject {        public void test1();        public void test2();    }    /**     * 实现类1     */    static class MySubject1 implements Subject {        public void test1() {            System.out.println("MySubject1 test1 方法开始执行");        }        public void test2() {            System.out.println("MySubject1 test2 方法开始执行");        }    }    /**     * 实现类2     */    static class MySubject2 implements Subject {        public void test1() {            System.out.println("MySubject2 test1 方法开始执行");        }        public void test2() {            System.out.println("MySubject2 test2 方法开始执行");        }    }    /**     * 定义一个动态代理类,动态代理类必须要实现InvocationHandler接口     */    static class DynamicProxy implements InvocationHandler {        private Subject target;        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {            System.out.println("before ");            method.invoke(target, args);            System.out.println("end");            return null;        }        //通过Proxy的newProxyInstance方法来创建我们的代理对象        public Object getProxy(Subject target) {            this.target = target;            //动态生成代理类            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);        }    }    public static void main(String[] args) {        DynamicProxy dynamicProxy = new DynamicProxy();        Subject subject = (Subject) dynamicProxy.getProxy(new MySubject1());        System.out.println("生成的代理类:" + subject.getClass());        subject.test1();        subject = (Subject) dynamicProxy.getProxy(new MySubject2());        System.out.println("生成的代理类:" + subject.getClass());        subject.test2();    }}



动态代理优点:
1.上面只有一个proxy类,但可以代理多个实现,而静态代理需要n个proxy类
2.通过invoke方法,在所有被代理的类的某些函数调用时触发,一口气完成所有对应代理的AOP(静态代理需要在每个代理上进行AOP)

原创粉丝点击