【Java学习笔记】代理模式详解

推荐大家去看动力节点的视频,更有助于理解

代理模式

一、如何理解代理模式

通过老杜的方法(类比现实场景)来理解代理模式,如下:

image-20230330155306312

1、代理模式的三大角色:目标对象、代理对象、公共接口

拍电影 代理模式
第一个角色 演员 目标对象
第二个角色 替身演员 代理对象
第三个角色 演员和替身演员具有相同的动作行为 目标对象和代理对象的公共接口

下面有代码去展示:

image-20230330155242665

三者的关系图如下:

image-20230330160030692

  • 三个之间的关系就是,目标对象代理对象都实现了同一个公共接口

2、代理模式的三个作用

1)保护自己

  • 在程序中,当一个对象需要受到保护的时候,可以考虑使用代理对象去完成某个行为。
  • 现实场景中, 演员害怕手上让替身演员(代理解析)演出,实现保护自己的作用

2)增强功能

  • 在程序中,需要给某个对象的功能进行功能增强的时候,可以考虑找一个代理进行增强。
  • 现实场景中,比如我们要租房子,可以自己租(目标对象),也可以找中介组(代理对象),实现了增强功能

3)代理交互

  • 在程序中,A对象无法和B对象直接交互时,也可以使用代理模式来解决。
  • 现实场景中,相亲前双方男女没见面,媒婆通过联系双方的父母(代理对象),实现了不同对象的沟通。

3、代理模式的实现方式

分为静态代理和动态代理

接下来会详细阐述

二、静态代理

1、深入浅出,从一个现实业务中常见的场景出发

引入老杜的例子:

某个项目的某个业务模块已经正常运行多年,项目经理要求对这些模块进行优化。首先提出的第一步简单的需求:要求显示每个模块(方法)执行的时间。比如我现在拿到这么一个需求,应该如何实现呢?

1)方法一,硬编码,直接修改原业务代码,在其基础上新增一个计时的业务代码。

image-20230330175917491

分析其优缺点

  • 优点:简单易懂,硬编码十分粗暴
  • 缺点:违反了OCP开闭原则,并且代码冗余

插一个知识点,什么是OCP开闭原则?

开闭原则 (The Open/Closed Principle, OCP) 规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的” 。其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化的。

该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要 代码审查 , 单元测试 以及诸如此类的用以确保产品使用品質的过程。

2)方法二:新建类继承原业务,在子类中重写父类的方法,实现业务需求

image-20230330180104593

分析优缺点

  • 优点:遵守了OCP开闭原则
  • 缺点:代码一样冗余,而且增加了耦合度(因为采用了继承关系)

3)引入代理模式,即使用代理对象,实现功能增强的作用

刚才提到,代理模式所需要的三大角色:目标对象,代理对象,公共接口,正常的业务中已经实现了【目标对象+公告接口】,还缺的就是一个代理对象。

那么代理对象在编码层就很简单,创建一个对象并实现公告的接口,同时,要求客户端在使用代理对象时,就行在使用目标对象一样

那么,静态代理在代码中如何实现呢?
  1. 首先创建一个代理对象并实现同一个公共接口
  2. 正常重写父类方法,并写好增强功能所需的业务逻辑
  3. 引用 目标对象(如何引用?
  4. 在代理对象内,调用目标对象的所对应的方法、
如何引用目标对象?看代码

image-20230330223532848

插入知识点:类与类之间的关系之二的【泛化关系和关联关系】

  • 泛化关系,就是继承,是一种 is a的关系
    • 比如说,苹果是水果,猫是动物,这是泛化关系
  • 关联关系,即引用,是一种has a的关系
    • 比如,人拥有苹果,人拥有猫,这是关联关系

2、静态代理模式有什么有优缺点

优点

  • 解决了OCP问题
  • 使用了关联关系,引入了has a的关系,降低了耦合

缺点

  • 代码依然冗余,假设系统中接口过多,每个接口都有一个代理对象,会出现【类爆炸】的情况

  • 不好维护(类过多,不利于后期再修改业务

为了克服静态代理模式的缺点,引入了动态代理

内存中动态生成字节码代理类的技术,叫做,动态代理
动态代理还是代理模式,只不过添加了字节码生成技术,可以在内存中为我们动态的生成一个cLass 字节码,这个字节码就是代理类。

三、动态代理

1、什么是动态代理?

前面已经提到了,动态代理就是【在内存】中动态生成【字节码代理类】的技术。(虽然不需要开发者书写,但是在内存层面依然存在该代理对象】

优点

  • 减少了代理类的数量
  • 并且解决了代码复用的问题。

动态代理常见的实现技术包括以下三种

  • JDK内置的动态代理技术 :只能代理接口
    • 位置:java.lang.reflect.Porxy ,是一个注解
  • CGLIB(Code Generation Library)动态代理技术,一个开源项目,生成类库,可以适用于接口和类
    • 但是CGLIB的低层是通过【继承】实现的(虽然是继承,但是由于是在内存动态生成字节码类,所以并不会增加耦合度),所以性能比JDK动态代理好
    • CGLIB的低层还有一个字节码处理框架 【ASM】(可能阅读源码时会遇到)
  • Javassist动态代理技术:东京大学的千叶滋教授所创建的开源项目。为JBOOS实现“aop”框架
    • mybatis框架底层就是用的javassist创建接口的字节码对象

Spring的低层主要是靠JDK内置的动态代理和CGLIB实现

猜你喜欢

转载自blog.csdn.net/Xcong_Zhu/article/details/129869145