从源码角度讲述动态代理的实现

不念不忘少年蓝@ 2023-09-24 21:21 107阅读 0赞

一、引言

Spring 中,最重要的应该当属 IOCAOP 了,IOC 的源码流程还比较简单,但 AOP 的流程就较为抽象了。

其中,AOP 中代理模式的重要性不言而喻,但对于没了解过代理模式的人来说,痛苦至极

于是,我就去看了动态代理的实现,发现网上大多数文章讲的都是不清不楚,甚至讲了和没讲似的,让我极其难受

本着咱们方向主打的就是源码,直接从从源码角度讲述一下 代理模式

兄弟们系好安全带,准备发车!

注意:本文篇幅较长,请留出较长时间来阅读

二、定义

代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

举个生活中常见的例子:客户想买房,房东有很多房,提供卖房服务,但房东不会带客户看房,于是客户通过中介买房。

format_png

这时候对于房东来说,不直接和客户沟通,而是交于中介进行代理

对于中介来说,她也会在原有的基础上收取一定的中介费

三、静态代理

我们创建 Landlord 接口如下:

  1. public interface Landlord {
  2. // 出租房子
  3. void apartmentToRent();
  4. }
  5. 复制代码

创建其实现类 HangZhouLandlord 代表杭州房东出租房子

  1. public class HangZhouLandlord implements Landlord {
  2. @Override
  3. public void apartmentToRent() {
  4. System.out.println("杭州房东出租房子");
  5. }
  6. }
  7. 复制代码

创建代理类 LandlordProxy,代表中介服务

  1. public class LandlordProxy {
  2. public Landlord landlord;
  3. public LandlordProxy(Landlord landlord) {
  4. this.landlord = landlord;
  5. }
  6. public void apartmentToRent() {
  7. apartmentToRentBefore();
  8. landlord.apartmentToRent();
  9. apartmentToRentAfter();
  10. }
  11. public void apartmentToRentBefore() {
  12. System.out.println("出租房前,收取中介费");
  13. }
  14. public void apartmentToRentAfter() {
  15. System.out.println("出租房后,签订合同");
  16. }
  17. }
  18. 复制代码

创建最终测试:

  1. public class JavaMain {
  2. public static void main(String[] args) {
  3. Landlord landlord = new HangZhouLandlord();
  4. LandlordProxy proxy = new LandlordProxy(landlord);
  5. // 从中介进行租房
  6. proxy.apartmentToRent();
  7. }
  8. }
  9. 复制代码

得出最终结果:

  1. 出租房前,收取中介费
  2. 杭州房东出租房子
  3. 出租房后,签订合同
  4. 复制代码

通过上述 demo 我们大概了解代理模式是怎么一回事

  • 优点:

    • 在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
  • 缺点:

    • 代理对象需要与目标对象实现一样的接口,所以会有很多代理类,一旦接口增加方法,目标对象与代理对象都要维护

四、动态代理

动态代理利用了JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能,动态代理又被称为JDK代理或接口代理。

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

  • 静态代理在编译时就已经实现了,编译完成后代理类是一个实际的 class 文件
  • 动态代理是在运行时动态生成的,即编译完成后没有实际的 class 文件,而是在运行时动态生成类字节码,并加载到 JVM

1、JDK代理

代码如下:

  1. public class ProxyFactory {
  2. // 目标方法
  3. public Object target;
  4. public ProxyFactory(Object target) {
  5. this.target = target;
  6. }
  7. public Object getProxyInstance() {
  8. return Proxy.newProxyInstance(
  9. // 目标对象的类加载器
  10. target.getClass().getClassLoader(),
  11. // 目标对象的接口类型
  12. target.getClass().getInterfaces(),
  13. // 事件处理器
  14. new InvocationHandler() {
  15. /**
  16. *
  17. * @param proxy 代理对象
  18. * @param method 代理对象调用的方法
  19. * @param args 代理对象调用方法时实际的参数
  20. * @return
  21. * @throws Throwable

发表评论

表情:
评论列表 (有 0 条评论,107人围观)

还没有评论,来说两句吧...

相关阅读

    相关 分析JDK动态代理

    引言 动态代理非常的重要,虽然我们在日常的工作中没有非常底层的 编写过动态代理的代码,但是动态代理却起着非常重要的功能,想一下我们经常使用的框架: 日志框架、AOP等等,