代理模式的定义:

代理模式是一个使用律非常高的模式,定义如下:

为其他对象提供一种代理,以控制对这个对象的访问。

类图:

简单的静态代理:

  1. public interface IRunner{
  2. //这是一个代理类和被代理类都需要实现的接口
  3. //在接口中定义一个抽象函数
  4. public void request();
  5. }
  6. //下面是真实的被代理类
  7. public class Runner implements IRunner{
  8. //实现接口中的方法
  9. public void request(){
  10. //实现具体的业务逻辑
  11. }
  12. }
  13. //下面是代理类
  14. public class RunnerAgent implements IRunner{
  15. //要代理哪个实现类
  16. private IRunner runner = null;
  17. //默认被代理者
  18. public RunnerAgent(IRunner runner){
  19. this.runner = runner;
  20. }
  21. //实现接口中定义的方法
  22. public void request(){
  23. this.before();
  24. this.runner.request();
  25. this.after();
  26. }
  27. //预处理
  28. private void before(){
  29. }
  30. //后处理
  31. private void after(){
  32. }
  33. }
  • 我们可以看到静态代理只能代理某一个类,每个类都有一个代理类。在对通用性要求更高的场景下(比如Spring AOP)传统的静态代理不能满足需求,会使类的数目非常庞大,因此又有了动态代理。

动态代理

什么是动态代理?动态代理就是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。动态代理的一个重要应用就是面向切面编程(AOP)

AOP示意图:

通过示意图可以明显的看出来,AOP抽取出非业务逻辑代码,降低了耦合度。对于日志、事务、权限等都可以在系统设计阶段不用考虑,而在设计后通过AOP的方式织入。

动态代理的通用类图(jdk动态代理,如无特殊声明,以下动态代理均指jdk动态代理)

图中类和接口的代码:

  1. //Subject接口
  2. public interface Subject{
  3. //业务操作
  4. public void doSomething(String str);
  5. }
  6. //真实主题RealSubject类
  7. public class RealSubject implements Subject{
  8. //业务操作
  9. public void doSomething(String str){
  10. System.out.println("do something!--->" + str);
  11. }
  12. }
  13. //动态代理的Handler类
  14. public class MyInvocationHandler implements InvocationHandler{
  15. //被代理对象
  16. private Object target = null;
  17. //构造函数
  18. public MyInvocationHandler(Object _obj){
  19. this.target = _obj;
  20. }
  21. //代理方法 覆盖接口InvocationHandler中的invoke方法
  22. @Override
  23. public Object invoke(Object proxy, Method method, Object[] args)
  24. throws Throwable{
  25. //执行被代理的方法
  26. return method.invoke(this.target, args);
  27. }
  28. }
  29. //动态代理类
  30. public class DynamicProxy<T>{
  31. public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {
  32. if(true) {
  33. //执行一个前置通知
  34. (new BeforeAdvice()).exec();
  35. }
  36. //执行目标函数
  37. return (T) Proxy.newProxyInstance(loader, interfaces, h);
  38. }
  39. }
  40. //通知接口及其实现
  41. public interface IAdvice{
  42. //通知方法
  43. public void exec();
  44. }
  45. public class BeforeAdvice implements IAdvice{
  46. public void exec(){
  47. System.out.println("我是前置通知,我被执行了!");
  48. }
  49. }
  50. //动态代理场景类
  51. public class Client{
  52. public static void main(String[] args){
  53. //定义一个主题
  54. Subject subject = new RealSubject();
  55. //定义一个Handler
  56. InvocationHandler handler = new MyInvocationHandler(subject);
  57. //定义主题的代理
  58. Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().
  59. getClassLoader(), subject.getClass.getInterfaces(),handler);
  60. //代理行为
  61. proxy.doSomething("Finish");
  62. }
  63. }

运行结果:

  1. 我是前置通知,我被执行了!
  2. do something!--->Finish

其中有这样的一行代码:return (T) Proxy.newProxyInstance(loader, interfaces, h);

这里使用interfaces指出了被代理对象实现的接口中的方法,因此jdk动态代理就要求被代理类必须实现接口。

h是接口InvocationHandler的实现类MyInvocationHandler的实例。由h对象的invoke方法负责接管被代理类实现的接口中的方法。

在运行时,只需通过subject.getClass.getInterfaces()传参,通过反射,达到了解耦的目的。

  • jdk动态代理 vs cglib动态代理

    jdk动态代理是以接口为中心的,相当于添加类一种对于被调用者没有太大意义的限制。我们实例化的是代理对象,而不是真正被调用的类型,这在实践中可能带来不便。

    如果被调用者没有实现接口,而我们还是希望利用动态代理机制,那么可以考虑其他方式。我们知道Spring AOP支持两种模式的动态代理:jdk动态代理和cglib。如果我们选择cglib方式,就不再依赖接口。

    cglib动态代理采取的方式是创建被代理类的子类。因此要求被代理类不可以用final修饰。

    jdk动态代理的优势:

    最小化依赖关系

    代码实现简单。

    cglib代理优势:

    不需要被代理类实现额外接口。

    只操作我们关心的类,而不必为其他相关类增加工作量。

    高性能。

代理模式的优点

  • 职责清晰

    真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。
  • 高扩展性

    具体主题角色是随时都会发生变化的。只要实现了接口,不管如何变化,都离不开接口的规范,那我们的代理类完全就可以在不做任何修改的情况下使用。

参考文献:设计模式之禅 秦小波 著

浅谈代理模式与java中的动态代理的更多相关文章

  1. 代理模式与java中的动态代理

    前言    代理模式又分为静态代理与动态代理,其中动态代理是Java各大框架中运用的最为广泛的一种模式之一,下面就用简单的例子来说明静态代理与动态代理. 场景    李雷是一个唱片公司的大老板,很忙, ...

  2. 10分钟了解 代理模式与java中的动态代理

    前言    代理模式又分为静态代理与动态代理,其中动态代理是Java各大框架中运用的最为广泛的一种模式之一,下面就用简单的例子来说明静态代理与动态代理. 场景    李雷是一个唱片公司的大老板,很忙, ...

  3. 十分钟理解Java中的动态代理

    十分钟理解 Java 中的动态代理   一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道 ...

  4. 深度剖析java中JDK动态代理机制

    https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...

  5. 一文读懂Java中的动态代理

    从代理模式说起 回顾前文: 设计模式系列之代理模式(Proxy Pattern) 要读懂动态代理,应从代理模式说起.而实现代理模式,常见有下面两种实现: (1) 代理类关联目标对象,实现目标对象实现的 ...

  6. 使用Java中的动态代理实现数据库连接池

    2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的 ...

  7. java中的动态代理机制

    java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...

  8. Java 中的动态代理

    一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者” ...

  9. Java中的动态代理(jdk和cglib)

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类 ...

随机推荐

  1. SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂)

    SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂) 在实际开发过程中,经常会碰见一些比如系统启动初始化信息.统计在线人数.在线用户数.过滤敏/高词汇.访问权限控制(URL级别 ...

  2. websocket报400错误

    解决方案看了下讨论区说的方案,问题出现在nginx的配置文件,需要修改nginx.conf文件.在linux终端中敲入vim /etc/nginx/nginx.conf,找到location这个位置, ...

  3. Linux 系统编程 学习:06-基于socket的网络编程1:有关概念

    Linux 系统编程 学习:006-基于socket的网络编程1:有关概念 背景 上一讲 进程间通信:System V IPC(2)中,我们介绍了System IPC中关于信号量的概念,以及如何使用. ...

  4. Elasticsearch原理解析与性能调优

    基本概念 定义 一个分布式的实时文档存储,每个字段 可以被索引与搜索 一个分布式实时分析搜索引擎 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据 用途 全文检索 结构化搜索 分 ...

  5. Ubuntu 18.04.2 LTS美化方案

    Ubuntu 18.04.2 LTS美化方案记录 根据个人经验,我将Ubuntun美化分为四个部分:1)桌面:2)对话框界面:3)图标:4)登录及锁屏界面:5)终端.由于Ubuntu系统默认采用GNO ...

  6. python爬虫04 Requests

    接下来我们要来玩一个新的库 这个库的名称叫做 Requests 这个库比我们上次说的 urllib 可是要牛逼一丢丢的 毕竟 Requests 是在 urllib 的基础上搞出来的 通过它我们可以用更 ...

  7. SpringBoot第九集:整合JSP和模板引擎Freemarker/Thymeleaf(2020最新最易懂)

    SpringBoot第九集:整合JSP和模板引擎(2020最新最易懂) 当客户通过前端页面提交请求后,我们以前是怎么做的?后端接收请求数据,处理请求,把响应结果交给模板引擎JSP,最后将渲染后的JSP ...

  8. tcp 拥塞控制引擎&状态机

    TCP核心:流量控制   拥塞控制 流量控制:滑动窗口来实现, 防止接收方能够处理过来 拥塞控制:防止过多的包被发送到网络中,避免出现网络负载过大 说一说 拥塞控制: 拥塞控制状态机的状态有五种,分别 ...

  9. c++与c

    const char* c_str ( ) const; Get C string equivalent Generates a null-terminated sequence of charact ...

  10. 守护进程详解以及start-stop-daemon命令

    1.概念:守护进程是在后台运行的不受终端控制的进程,通常守护进程在系统启动时自动运行,守护进程的名称通常以d结尾,比如sshd.xinetd.crond等. 2.创建守护进程的步骤:a.调用fork( ...