您的位置:首页 > 编程语言 > Java开发

java动态代理反射剖析

2016-07-17 10:33 330 查看
对jdk的动态代理研究了几天,写一篇博客总结下:

在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾。

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:

用起来是比较简单,但是如果能知道它背后做了些什么手脚,那就更好不过了。首先来看一下JDK是怎样生成代理对象的。既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么?

java.lang.reflect.Proxy:Proxy 提供用于创建动态代理类和实例的静态方法.

newProxyInstance():返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序

(详见api文档)

java.lang.reflect.InvocationHandler:InvocationHandler 是代理实例的调用处理程序 实现的接口。

invoke():在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上

调用此方法。
http://www.51testing.com/?uid-202848-action-viewspace-itemid-229928
JDK1.2以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个拦截处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行商业方法,在商业方法被调用的同时,执行处理器会被自动调用。  

Java动态代理只能对实现了接口的类生成代理,不能针对类。其实现主要是通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现。

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

 //返回业务对象的代理对象  

HelloWorld proxy = (HelloWorld)Proxy.newProxyInstance(   

        obj.getClass().getClassLoader(),    

        obj.getClass().getInterfaces(),    

        handler);   

   

//通过代理对象执行业务对象的方法  

proxy.sayHelloWorld();


Proxy 静态方法 newProxyInstance: 通过反射获取构造函数对象并生成代理类实例
public static Object newProxyInstance(ClassLoader loader,

            Class<?>[] interfaces,

            InvocationHandler h)

            throws IllegalArgumentException {

    

    // 检查 h 不为空,否则抛异常

    if (h == null) {

        throw new NullPointerException();

    }

    // 获得与制定类装载器和一组接口相关的代理类类型对象

    Class cl = getProxyClass(loader, interfaces);

    // 通过反射获取构造函数对象并生成代理类实例

    try {

        Constructor cons = cl.getConstructor(constructorParams);

        return (Object) cons.newInstance(new Object[] { h });

    }catch (NoSuchMethodException e) { throw new InternalError(e.toString()); 

    }catch (IllegalAccessException e) { throw new InternalError(e.toString()); 

    }catch (InstantiationException e) { throw new InternalError(e.toString()); 

    }catch (InvocationTargetException e) { throw new InternalError(e.toString()); 

    }

}

        

博客部分借鉴:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/

博客部分借鉴:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息