这样和妻子解释:Java动态代理机制详解(JDK和CGLIB( 五 )


InvocationHandler角色的由来
仔细思考代理模式中的代理Proxy角色 。 Proxy角色在执行代理业务的时候 , 无非是在调用真正业务之前或者之后做一些“额外”业务 。
这样和妻子解释:Java动态代理机制详解(JDK和CGLIB文章插图
有上图可以看出 , 代理类处理的逻辑很简单:在调用某个方法前及方法后做一些额外的业务 。 换一种思路就是:在触发(invoke)真实角色的方法之前或者之后做一些额外的业务 。 那么 , 为了构造出具有通用性和简单性的代理类 , 可以将所有的触发真实角色动作交给一个触发的管理器 , 让这个管理器统一地管理触发 。 这种管理器就是Invocation Handler 。
动态代理模式的结构跟上面的静态代理模式稍微有所不同 , 多引入了一个InvocationHandler角色 。
先解释一下InvocationHandler的作用:
在静态代理中 , 代理Proxy中的方法 , 都指定了调用了特定的realSubject中的对应的方法:在上面的静态代理模式下 , Proxy所做的事情 , 无非是调用在不同的request时 , 调用触发realSubject对应的方法;更抽象点看 , Proxy所作的事情;在Java中 方法(Method)也是作为一个对象来看待了 ,动态代理工作的基本模式就是将自己的方法功能的实现交给 InvocationHandler角色 , 外界对Proxy角色中的每一个方法的调用 , Proxy角色都会交给InvocationHandler来处理 , 而InvocationHandler则调用具体对象角色的方法 。 如下图所示:
这样和妻子解释:Java动态代理机制详解(JDK和CGLIB文章插图
在这种模式之中:代理Proxy 和RealSubject 应该实现相同的功能 , 这一点相当重要 。 (我这里说的功能 , 可以理解为某个类的public方法)
在面向对象的编程之中 , 如果我们想要约定Proxy 和RealSubject可以实现相同的功能 , 有两种方式:
a.一个比较直观的方式 , 就是定义一个功能接口 , 然后让Proxy 和RealSubject来实现这个接口 。
b.还有比较隐晦的方式 , 就是通过继承 。 因为如果Proxy 继承自RealSubject , 这样Proxy则拥有了RealSubject的功能 ,
Proxy还可以通过重写RealSubject中的方法 , 来实现多态 。
其中JDK中提供的创建动态代理的机制 , 是以a 这种思路设计的 , 而cglib 则是以b思路设计的 。
JDK的动态代理创建机制----通过接口
比如现在想为RealSubject这个类创建一个动态代理对象 , JDK主要会做以下工作:
1. 获取 RealSubject上的所有接口列表;2. 确定要生成的代理类的类名 , 默认为:com.sun.proxy.$ProxyXXXX ;3. 根据需要实现的接口信息 , 在代码中动态创建 该Proxy类的字节码;4 . 将对应的字节码转换为对应的class 对象;5. 创建InvocationHandler 实例handler , 用来处理Proxy所有方法调用;6. Proxy 的class对象 以创建的handler对象为参数 , 实例化一个proxy对象
JDK通过 java.lang.reflect.Proxy包来支持动态代理 , 一般情况下 , 我们使用下面的newProxyInstance方法
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)返回一个指定接口的代理类实例 , 该接口可以将方法调用指派到指定的调用处理程序 。 而对于InvocationHandler , 我们需要实现下列的invoke方法:
在调用代理对象中的每一个方法时 , 在代码内部 , 都是直接调用了InvocationHandler 的invoke方法 , 而invoke方法根据代理类传递给自己的method参数来区分是什么方法 。
Object invoke(Object proxy,Method method,Object[] args)在代理实例上处理方法调用并返回结果 。 讲的有点抽象 , 下面通过一个实例来演示一下吧:


推荐阅读