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

按照代理的创建时期,代理类可以分为两种:
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态:在程序运行时运用反射机制动态创建而成。

静态代理类优缺点

优点:
代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合),对于如上的客户端代码,newUserManagerImpl()可以应用工厂将它隐藏。

缺点:
1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。如上的代码是只为UserManager类的访问提供了代理,但是如果还要为其他类如Department类提供代理的话,就需要我们再次添加代理Department的代理类。
举例说明:代理可以对实现类进行统一的管理,如在调用具体实现类之前,需要打印日志等信息,这样我们只需要添加一个代理类,在代理类中添加打印日志的功能,然后调用实现类,这样就避免了修改具体实现类。满足我们所说的开闭原则。但是如果想让每个实现类都添加打印日志的功能的话,就需要添加多个代理类,以及代理类中各个方法都需要添加打印日志功能(如上的代理方法中删除,修改,以及查询都需要添加上打印日志的功能)
即静态代理类只能为特定的接口(Service)服务。如想要为多个接口服务则需要建立很多个代理类。

动态代理优点:

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强

根据如上的介绍,你会发现每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类
所以我们就会想办法可以通过一个代理类完成全部的代理功能,那么我们就需要用动态代理。
而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象,在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持

java.lang.reflect.InvocationHandler接口的定义如下:

//Object proxy:被代理的对象
//Method method:要调用的方法
//Object[] args:方法调用时所需要参数
public interface InvocationHandler {  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

java.lang.reflect.Proxy类的定义如下:

//CLassLoader loader:类的加载器
//Class<?> interfaces:得到全部的接口
//InvocationHandler h:得到InvocationHandler接口的子类的实例
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException

具体实现类

public class UserManagerImpl implements UserManager {  @Override  public void addUser(String userId, String userName) {  System.out.println("UserManagerImpl.addUser");  }  @Override  public void delUser(String userId) {  System.out.println("UserManagerImpl.delUser");  }  @Override  public String findUser(String userId) {  System.out.println("UserManagerImpl.findUser");  return "张三";  }  @Override  public void modifyUser(String userId, String userName) {  System.out.println("UserManagerImpl.modifyUser");  }  }

动态创建代理对象的类

//动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类  public class LogHandler implements InvocationHandler {  // 目标对象  private Object targetObject;  //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。              public Object newProxyInstance(Object targetObject){  this.targetObject=targetObject;  //该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例    //第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器  //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口  //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法  //根据传入的目标返回一个代理对象  return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  targetObject.getClass().getInterfaces(),this);  }  @Override  //关联的这个实现类的方法被调用时将被执行  /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/  public Object invoke(Object proxy, Method method, Object[] args)  throws Throwable {  System.out.println("start-->>");  for(int i=0;i<args.length;i++){  System.out.println(args[i]);  }  Object ret=null;  try{  /*原对象方法调用前处理日志信息*/  System.out.println("satrt-->>");  //调用目标方法  ret=method.invoke(targetObject, args);  /*原对象方法调用后处理日志信息*/  System.out.println("success-->>");  }catch(Exception e){  e.printStackTrace();  System.out.println("error-->>");  throw e;  }  return ret;  }  }

被代理对象targetObject通过参数传递进来,我们通过targetObject.getClass().getClassLoader()获取ClassLoader对象,然后通过targetObject.getClass().getInterfaces()获取它实现的所有接口,然后将targetObject包装到实现了InvocationHandler接口的LogHandler对象中。通过newProxyInstance函数我们就获得了一个动态代理对象。

客户端代码

public class Client {  public static void main(String[] args){  LogHandler logHandler=new LogHandler();  UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());  //UserManager userManager=new UserManagerImpl();  userManager.addUser("1111", "张三");  }
}

可以看到,我们可以通过LogHandler代理不同类型的对象,如果我们把对外的接口都通过动态代理来实现,那么所有的函数调用最终都会经过invoke函数的转发,因此我们就可以在这里做一些自己想做的操作,比如日志系统、事务、拦截器、权限控制等。这也就是AOP(面向切面编程)的基本原理。

静态代理和动态代理的区别相关推荐

  1. 代理模式详解(静态代理和动态代理的区别以及联系)

    原文链接:https://www.cnblogs.com/takumicx/p/9285230.html 1. 前言 代理模式可以说是生活中处处可见.比如说在携程上定火车票,携程在这里就起到了一个代理 ...

  2. 静态代理,cglib动态代理,jdk动态代理区别以及流程详解

    1.静态代理 静态代理使用的是代理设计模式,不讲高大上的思想,我们直接实战 这是动物接口,其中有一个吃饭方法 这是其中的一只动物,实现了动物接口,覆盖了吃饭方法 现在我们思考,我想要给猫找一个代理,希 ...

  3. JAVA静态代理和动态代理的区别?

    代理简述 代理是英文 Proxy 翻译过来的.我们在生活中见到过的代理,大概最常见的就是朋友圈中卖面膜的同学了. 他们从厂家拿货,然后在朋友圈中宣传,然后卖给熟人. 按理说,顾客可以直接从厂家购买产品 ...

  4. Java设计模式学习06——静态代理与动态代理(转)

    原地址:http://blog.csdn.net/xu__cg/article/details/52970885 一.代理模式 为某个对象提供一个代理,从而控制这个代理的访问.代理类和委托类具有共同的 ...

  5. SpringAOP静态代理和动态代理

    代理模式应用于SpringAOP. SpringAOP.即面向切面的编程范式.多用于权限控制,异常处理,日志管理等场景.主要作用是分离功能性需求和非功能性需求,减少代码冗余.我们在使用的时候可以集中处 ...

  6. Java静态代理、动态代理与CGLib代理

    java的动态代理举足轻重,它同反射原理一直是许多框架的底层实现.今天唠一下. 一.代理模式 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标 ...

  7. 【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)

    文章目录 什么是代理模式 一. 代理模式简介 二. 静态代理模式 三. 动态代理模式 万能模版 前言:笔记基于狂神设计模式视频.<大话设计模式>观后而写 (最近一直在更新之前的刷题博客,今 ...

  8. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  9. Spring系列之静态代理、动态代理、cglib代理与Spring AOP的处理

    本章内容 代理的概念及理解 如何实现静态代理 如何实现动态代理 静态代理与动态代理有什么区别与优缺点 JDK动态代理如何实现 cglib动态代理如何实现 JDK动态代理与cglib动态代理的区别 Sp ...

  10. Java设计模式(五)代理设计模式—静态代理—JDK动态代理—Cglib动态代理

    文章目录 什么是代理模式 代理模式应用场景 代理的分类 静态代理 什么是静态代理 深入解析静态代理 小结 动态代理 什么是动态代理 JDK动态代理 原理和实现方式 代码实现 优缺点 Cglib动态代理 ...

最新文章

  1. 16进制转string java_java的2/10/16进制转换和字符串数字转换
  2. C++知识点19——使用C++标准库(再谈string——string的初始化、赋值、添加、删除、访问)
  3. python第三方库排行-Python模块汇总(常用第三方库)
  4. Launcher3自定义壁纸旋转后拉伸无法恢复
  5. 在android C/C++ native编程(ndk)中使用logcat
  6. 智能合约开发环境搭建及 Hello World 合约
  7. 【Linux】一步一步学Linux——wall命令(237)
  8. 《深入理解Spark-核心思想与源码分析》(四)第四章存储体系
  9. 上元之夜丨《大数据》与您共度佳节!
  10. 腾讯2021春季校园招聘启动
  11. 【UML】协作图Collaboration diagram(交互图)(转)
  12. 当今互联网从业者必看书籍 -- 《自传播》
  13. c语言输出26个小写英文字母,c语言题。 按顺序打印输出26个英文字母,
  14. 【黑灰产犯罪研究】网络水军
  15. Docker Engine 安装时遇到的坑
  16. 快速接入 微信微博QQ钉钉 原生登录分享
  17. 16、基于51单片机智能浇花自动浇水灌溉土壤湿度检测报警系统设计
  18. html+js在前端实现条码枪功能Demo
  19. mysql month函数值类型_MySQL常用函数(分类别整理)
  20. DataGrid_单击_双击_editable

热门文章

  1. 自媒体原创检测工具,了解了这个离收获大量粉丝不会远啦!
  2. lisp弧度转度分秒_度分秒转弧度)
  3. TPC-DS标准规范(2)
  4. oracle dmp 编码问题,Oracle imp导入dmp文件时 IMP-00038:无法转换为环境字符集句柄
  5. java 微信 图灵机器人_使用图灵api创建微信聊天机器人
  6. ubantu网络调试助手的安装以及打开
  7. 大数据下的图片类别以及图片爬取详细的过程(一)
  8. AD18快速简单入门,画电路原理图以及PCB图
  9. 在取证过程中,常见的一些注册表键值整理
  10. 大数据学习---HIVE入门SQL学习