JDK动态代理

Spring AOP使用了两种代理机制:  一种是基于JDK的动态代理;  一种是基于 CGLib 的动态代理.

JDK本身只提供接口代理,  而不支持类的代理.

JDK动态代理主要涉及 java.lang.reflect 包中的两个类:  Proxy 和 InvocationHandler.

InvocationHandler 是一个接口,  可以通过实现该接口定义横切逻辑,  并通过反射机制调用目标类中的代码,  动态地将横切逻辑和业务逻辑编织在一起.  Proxy利用 InvocationHandler 动态创建一个符合某一接口的的实例,  生成目标类的代理对象.

一. JDK动态代理的使用

使用 InvocationHandler 将业务逻辑代码与横切逻辑代码编织到一起

invoke() 方法将横切逻辑代码与业务逻辑代码编织到一起,  可以将 InvocationHandler 看成编织器.

实现 InvocationHandler 接口, 实现了一个 invoke() 方法.  invoke(Object  proxy,Method  method,Object[] args).  proxy是最终生成的代理实例;  method 是被代理目标实例的某个具体方法;  args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用. 在构造函数中, target 是希望被代理的目标对象.

通过 Proxy 创建接口的代理实例

通过  Proxy 的 newProxyInstance() 静态方法为编织了业务逻辑和监视逻辑的 handler 创建一个符合 Interface 接口的代理实例. 

该方法的第一个参数为类加载器,  第二个参数为创建代理实例所需实现的一组接口,  第三个参数为整合了业务逻辑和横切逻辑的编织器对象.

二. JDK动态代理的原理

我们使用代理类  Proxy  创建了一个代理实例,  这个代理实例执行接口中的方法实际上是执行了  InvocationHandler接口  实现类中的 invoke() 方法中自定义编织到一块的横切逻辑和业务逻辑代码.  我们查看一下 Proxy 类的源码, 简单概述以下代理实例的创建过程.

1.  newProxyInstance 方法

2.着重看一下 getProxyClass0() 方法.

proxyClassCache 代理缓存实际上使用了 WeakCache 缓存类来实现的.

3.如果根据提供的类加载器和接口数组在缓存中能找到代理类就直接返回该代理类,  否则调用 ProxyClassFactory 去生成代理类.

先不用关注缓存机制,  着重看下 ProxyClassFactory 是如何生成代理类的.

4. 来看一下 ProxyGenerator.generateProxyClass() 是如何生成代理类的字节码文件的

5.我们可以读取Proxy 生成的字节码文件, 通过反编译, 将Class文件输出

可以得到代理类,代码如下:

总结,  JDK生成代理类的特征:

代理类继承了 Proxy 类,  实现了代理的接口,  由于Java不能多继承,  这里已经继承了  Proxy 类,  不能再继承其他类了,  所以JDK动态代理不支持对实现类的代理,  只支持对接口的代理.

提供一个 InvocationHandler  作为构造方法的入参.

生成静态代码块初始化接口中的方法.  JDK动态代理除了代理接口中的方法,  还代理了Object 类中的 equals(), toString(), hashCode() 方法.

代理类调用接口中的方法,  实际是调用了 InvocationHandler 中的 invoke() 方法. 从而实现了对接口的代理.

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值