1、代理模式定义

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。比如租房中介,我们想租房的时候找租房中介,租房中介是户主的代理,代替户主带着租客看房、签约等后续后续操作。此模式的UML图如下:

2、代理模式的使用场景

(1)控制访问:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

2)功能增强(符合开闭原则):代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。(也即,代理类一方面调用了被代理对象的方法,同时可以增加一些新的功能,与装饰者模式有一些类似之处)

3、三种动态代理方式

(1)静态代理

a、新建一个接口interface

b、创建被代理对象类(目标类),需要实现interface

c、创建代理类,需要实现interface

d、测试类

新建一个接口interface
public interface CommonInterface {void print(String string);
}
创建被代理对象类(目标类),需要实现interface
public class Target implements CommonInterface {public void print(String string) {System.out.println("this is CommonInterface and param is "+ string);}
}
创建代理类,需要实现interface
public class ProxyClass implements CommonInterface {// 静态代理的静态就体现在这里,把被代理的类对象硬编码。private Target target = new Target();public void print(String string) {System.out.println("before target");target.print(string);System.out.println("after target");}
}
测试类
public class Main {public static void main(String[] args) {ProxyClass proxyClass = new ProxyClass();proxyClass.print("wangwang");}
}

打印结果:

before target

this is CommonInterface and param is wangwang

after target

(2)动态代理

a、新建一个接口interface

b、创建被代理对象类(目标类),需要实现interface

c、创建代理类,需要实现InvocationHandler

d、测试类

新建一个接口interface
public interface CommonInterface {int caculate(int a);
}
创建被代理对象类(目标类),需要实现interface
public class Target implements CommonInterface {public int caculate(int a) {return a * 2;}
}
创建代理类,需要实现interface
public class DynamicProxy implements InvocationHandler {private Object target = null;public DynamicProxy(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;// 调用目标的方法result = method.invoke(target,args);// 方法增强,增加新的功能逻辑if(result != null){Integer res = (Integer)result;res += 5;result = res;}return result;}
}
 
测试类
public class Main {public static void main(String[] args) {// 1、创建目标对象Target target = new Target();// 2、创建handler对象DynamicProxy dynamicProxy = new DynamicProxy(target);///3、创建代理对象CommonInterface proxy = (CommonInterface)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),dynamicProxy);System.out.println(proxy.caculate(2));}
}

数据结果:9

注:Proxy.newProxyInstance()方法接受三个参数:
ClassLoader loader : 指定当前目标对象使用的类加载器,获取加载器的方法是固定的
Class<?>[] interfaces : 指定目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler : 指定动态处理器,执行目标对象的方法时,会触发事件处理器的方法

虽然相对于静态代理,动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。

(3)cglib实现代理

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。但因为采用的是继承,所以不能对final修饰的类进行代理。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

需要先引入cglib的包或者依赖

如果是maven项目,通过在pom文件中加入如下依赖引入:

引入cglib依赖
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version>
</dependency>

被代理的类

public class OldMethod {public void print(){System.out.println("hello world");}
}
代理过程,实现接口MethodInterceptor
public class  CglibProxy implements MethodInterceptor {public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("before cglib");Object result = methodProxy.invokeSuper(o, objects);System.out.println("after cglib");return result;}
}
测试类
public class CglibProxyTest {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(OldMethod.class);enhancer.setCallback(new CglibProxy());OldMethod cglibProxy = (OldMethod)enhancer.create();cglibProxy.print();}
}

输入结果:

before cglib
hello world
after cglib

       CGLIB创建的动态代理对象比JDK创建的动态代理对象的性能更高,但是CGLIB创建代理对象时所花费的时间却比JDK多得多。所以对于单例的对象,因为无需频繁创建对象,用CGLIB合适,反之使用JDK方式要更为合适一些。同时由于CGLib由于是采用动态创建子类的方法,对于final修饰的方法无法进行代理。

代理模式——案例分析与代码演示相关推荐

  1. 建造者模式——案例分析与代码演示

    1.概述 建造者模式多用在对象构成比较复杂的场景中,比如汽车.电脑等包含的组件数量和种类很多很大的情形下.建造者(Builder)模式的定义如下,把一个复杂对象的构造与它的装配分离,使同样的构造过程可 ...

  2. html中放大镜案列,Canvas实现放大镜效果完整案例分析(附代码)

    本文主要记录 canvas 在图像.文字处理.离屏技术和放大镜特效的实现过程中使用到的api.先看下效果吧: 一张模糊的图片: 鼠标点击任意位置,产生放大效果: 哇塞~ 一个帅哥,哈哈哈哈~ 1.放大 ...

  3. DL之Keras:基于Keras框架建立模型实现【预测】功能的简介、设计思路、案例分析、代码实现之详细攻略(经典,建议收藏)

    DL之Keras:基于Keras框架建立模型实现[预测]功能的简介.设计思路.案例分析.代码实现之详细攻略(经典,建议收藏) 目录 Keras框架使用分析 Keras框架设计思路 案例分析 代码实现 ...

  4. 抢红包案例分析以及代码实现(二)

    概述 上一篇文章中使用ssm+mysql实现,存在并发超发问题,这里我们使用悲观锁的方式来解决这个逻辑错误,并验证数据一致性和性能状况. 超发问题分析 针对这个案例,用户抢到红包后,红包总量应-1,当 ...

  5. html放大镜原理,Canvas实现放大镜效果完整案例分析(附代码)

    本文主要记录 canvas 在图像.文字处理.离屏技术和放大镜特效的实现过程中使用到的API.先看下效果吧: 一张模糊的图片: 鼠标点击任意位置,产生放大效果: 哇塞~ 一个帅哥,哈哈哈哈~ 1.放大 ...

  6. 抢红包案例分析以及代码实现(三) 侵立删

    转自:https://mp.weixin.qq.com/s/Pp-nCYrzXXXfLcFFS_ttWg 前文回顾 抢红包案例分析以及代码实现(一) 抢红包案例分析以及代码实现(二) 接下来我们使用乐 ...

  7. 案例分析 | 无代码助力国企数字化转型破旧立新

    数字经济已成为国策,国企数字化转型更是排头兵,正成为数字化转型标杆.企业数字化转型是用信息技术全面重塑企业经营管理模式,是企业发展模式的变革与创新,是迈向数字经济时代的必然选择. 2022年9月底,国 ...

  8. android 类似金山词霸 每日一句源代码 csdn,个人作业2——英语学习APP案例分析(示例代码)...

    第一部分 调研, 评测 软件:微软必应词典(Android客户端) 版本:5.5.2 第一次上手体验: 整体界面上还算简洁,功能也算完全,但是并没有什么特别吸引我的地方.就我个人而言,如果不是这次作业 ...

  9. JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式

    本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...

最新文章

  1. R语言ggplot2可视化:ggplot2中使用element_text函数设置轴标签文本粗体字体(bold text,使x轴和Y轴的标签文本都使用粗体字体)、注意是轴标签而非轴标题
  2. 计算机专业美国最好的学校排名,美国计算机专业大学排名
  3. mysql基础小测试三_数据库---MySQL(三)
  4. 不得了了!Python 又爆出重大 Bug!
  5. ORACLE中的异常处理
  6. 服务端断开_Java多线程技术:实现多用户服务端Socket通信
  7. git缓冲区查看_git原理学习记录:从基本指令到背后原理,实现一个简单的git
  8. Postman查看完整的请求报文
  9. Cookie介绍与操作
  10. java开发 网关_SpringCloud系列之网关(Gateway)应用篇
  11. [Usaco2011][bzoj2442][洛谷2527]修剪草坪解题报告(dp,贪心,单调队列)
  12. 盘点40种常用的芯片封装技术
  13. 使用ViewPage + Fragment,ViewPage所在的activity重建时的问题
  14. 使用ps替换图片颜色为透明色
  15. 有关十二个“一”的文艺创作-拓展版
  16. 如何用matlab绘制心形线,心形线的matlab程序
  17. k8s集群重新将master节点加入集群
  18. 六、MySQL之数据定义语言(一)
  19. 2021年中国亚马逊耳环市场趋势报告、技术动态创新及2027年市场预测
  20. 在下列集成电路说法中不正确_关于集成电路(IC),下列说法中,正确的是______

热门文章

  1. 蓝汛之获取DAC输出能量【篇】
  2. 25岁,我明白了这些道理
  3. 网站都变成灰色了,它是怎么实现的
  4. Flowable-6.6.0 工作流引擎(windows平台zip包)下载
  5. 【OBS】OBS预览
  6. Preface---ITE EC
  7. 电子器件系列31:ULN2003 芯片详解
  8. java 求一组数据的各自所占百分比
  9. 2020年中国嵌入式软件市场现状分析,国家政策大力支持行业发展「图」
  10. 【机器学习理论】第1部分 机器学习基础