Java 原生基于接口的动态代理

参考文章

java dynamic proxies

前言

代理可以看做是一种封装, 最终会把功能调用传递给背后真正的实现方。 使用代理的原因往往是因为背后的真实实现方不便于直接被调用(可能是一个远程对象) 或者需要为被代理的功能添加一些辅助功能。

注: 根据 GoF 设计模式原书的描述, 代理模式和装饰器模式的实现方式是完全一样的, 其区别主要在于使用场景

  • 代理模式的目的在于进行 访问控制, 其意图在于为被代理对象提供一个替身, 而之所以提供替身而不直接访问的目的是, 原有的被代理对象可能不便于被直接访问(是一个远程对象), 或者是一个访问权限需要被限制的对象。
  • 装饰器模式的目的在于进行功能添加 / 功能增强 , 其意图在于为被装饰对象动态地增加功能或属性

笔者认为这种说法是比较合理的, 毕竟一个代理,从业务逻辑角度来讲, 对被代理方应该是透明的。 就好比你委托一个中介替你完成一些事情, 他所达成的结果,应当和你的期待一致, 不应该有差别。所以代理如果要为被代理添加一些功能的话, 也应该是业务逻辑无关的功能,例如日志统计等功能。

动态代理和静态代理的区别:

  • 动态代理 中的代理关系是程序运行时产生的, 支持动态变化。 静态代理 的对象间代理关系是编译前就已经确定的, 在运行时刻, 是固定不变的。
  • 动态代理可以通过单一的一个类中的一个方法为多个类的多个方法提供代理服务。 动态代理允许你编写代码为任意的一种接口提供代理服务。
  • 其背后的工作原理,是针对特定接口, 创建代理类,使用者可以在这个代理类 Proxy 身上直接调用各种接口方法, 而代理类会把所有的方法调用都转发给一个单一的 handlerinvoke 方法, 完成真正的逻辑。

虽然动态代理在日常开发中并不经常使用,但是对于框架编写者而言, 动态代理非常实用。
动态代理也是 Spring AOP 的实现基础, 本文旨在梳理一下 Java 内置的动态代理实现方式, 供初学者学习参考

JAVA 原生动态代理

java 自带的动态代理方式是构建在 JDK 中的一个特性, 所以不需要引入任何额外的依赖即可使用。

但是有一个限制: java 内置的动态代理必须依托于接口

jdk 动态代理主要涉及到以下3个概念

  • 接口(Interface )
    • 这里以一个 FooInterface 进行举例, FooInterface 中有一个 foo() 方法必须实现
  • 代理类实例 ( Proxy Instance)
    • proxyInstance 是我们通过动态代理创建的代理类实例, 对外表现为实现了 FooInterface 接口
  • 调用处理器(Invocation Handler)
    • 对于proxyInstance 的方法调用, 会实际触发 invocationHandler.invoke() 函数

上述三个角色的逻辑工作关系是这样的 在这里插入图片描述

  • Tips: invocationHandler.invoke() 方法, 常常会把针对 proxyInstance 的调用进一步转发给其他类,这其实是引入了多层代理关系, 即 interface --> invocationHandler–> interfaceImpl 这有时会让部分读者产生困惑, 搞不清动态代理的核心工作机制。
  • 实际上, 读者仅需要记住, 动态代理本身最基础的逻辑就是完成一层代理关系, 即将针对某一接口的调用, 全部转发给一个 InvocationHandler 接口实现类的 invoke 方法。
  • 下面的例子一例子二, 分别展示了单层代理关系与多层代理关系的实现方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值