文章目录

  • 什么是代理模式
  • 代理模式应用场景
  • 代理的分类
  • 静态代理
    • 什么是静态代理
    • 深入解析静态代理
    • 小结
  • 动态代理
    • 什么是动态代理
    • JDK动态代理
      • 原理和实现方式
      • 代码实现
      • 优缺点
    • Cglib动态代理
      • 原理和简介
      • 代码实现
      • cglib代理的优缺点
    • CGLIB动态代理与JDK动态区别
    • Spring中代理的运用

什么是代理模式

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

通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用前处理,或调用后处理。例(AOP微实现) ,AOP核心技术面向切面编程。

代理模式应用场景

SpringAOP、事物原理、日志打印、权限控制、远程调用、安全代理(可以隐蔽真实角色)

  • 远程代理 :为位于两个不同地址空间对象的访问提供了一种实现机制,可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率。
  • 虚拟代理:通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销。
  • 缓冲代理:为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间。
  • 安全代理:可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限。
  • 智能引用:要为一个对象的访问(引用)提供一些额外的操作时可以使用

代理的分类

静态代理(静态定义代理类)

动态代理(动态生成代理类)

Jdk自带动态代理

Cglib 、javaassist(字节码操作库)

静态代理

什么是静态代理

由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

深入解析静态代理

场景

今天孔明想吃苹果,需要去超市购买,但是孔明比较懒,自己不想去,于是叫了外卖,然后超市派二狗子去给孔明送货。

代码实现

首先定义一个购买苹果的接口

public interface BuyApple {void buyApple();
}

孔明得到苹果的实现类

public class Kongming implements BuyApple {@Overridepublic void buyApple() {System.out.println("孔明得到了苹果...");}
}

超市让二狗子给孔明送货的代理类

public class TwoDog implements BuyApple {private BuyApple target;public TwoDog(BuyApple target) {this.target = target;}@Overridepublic void buyApple() {System.out.println("超市派二狗子送苹果...");target.buyApple();System.out.println("付款给超市...");}
}

客户端使用静态代理来操作

public class StaticProxy {public static void main(String[] args) {// 直接创建二狗子代理对象,为孔明送货TwoDog twoDog = new TwoDog(new Kongming());twoDog.buyApple();}
}
/* 运行结果
超市派二狗子送苹果...
孔明得到了苹果...
付款给超市...
*/

这便是一个简单的静态代理设计模式,孔明通过二狗子这个代理,得到了苹果。这里就是一个 AOP 的模式,在孔明得到苹果的前后,拓展了2个内容,超市派遣人员送货,超市收到货款。

小结

  1. 可以省去很多重复的代码,例如送货和付款的这部分代码,如果不使用代理,每个人都单独写一个购买苹果的方法,那么每个人都会有付款这段代码,造成大量的重复。
  2. 静态代理的缺点也很明显,在程序运行之前,代理类(二狗子)和委托类(孔明)的关系就确定了。如果此时,张三和李四也要购买苹果,那么就需要重新创建代理对象,new TowDog(new ZhangSan()) ,每一个顾客都要创建一个代理对象,这显然是极为不方便的

这种情况下,我们就需要考虑动态代理了。

动态代理

什么是动态代理

  1. 代理对象, 不需要实现接口
  2. 代理对象的生成, 是利用JDK的API, 动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
  3. 代理类和委托类之间的关系是动态确定的

JDK动态代理

原理和实现方式

原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理)

实现方式:

  1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
  2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
  3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
  4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
代码实现

新定义一个 JDKProxy 代理类,实现 InvocationHandler 接口

public class JDKProxy implements InvocationHandler {private Object target;public JDKProxy(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("超市派二狗子送苹果...");Object result = method.invoke(target, args);System.out.println("付款给超市...");return result;}
}

新增一个创建代理对象的工厂

public class JdkFactory {public static Object getProxy(Object target) {InvocationHandler handler = new JDKProxy(target);return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);}
}

使用Jdk动态代理完成调用

public class JdkClient {public static void main(String[] args) {Kongming kongming = new Kongming();BuyApple proxy = (BuyApple) JdkFactory.getProxy(kongming);proxy.buyApple();}
}
/* 打印结果
超市派二狗子送苹果...
孔明得到了苹果...
付款给超市...
*/
优缺点

优点:

  1. 不需要自己定义代理对象,由程序自动生成,可以根据程序运行环境创建对应的代理对象
  2. 不需要导入第三方 jar包,实现简单。

缺点:

  1. jdk动态代理,必须是面向接口,目标业务类必须实现接口,不能对没有实现接口的类做动态代理
  2. 因为代理类继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。

Cglib动态代理

原理和简介

Cglib动态代理原理是:利用asm开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

简介

使用cglib[Code Generation Library]实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码

使用时需要导入第三方依赖

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.5</version>
</dependency>
代码实现

还是孔明买苹果,定义业务类,被代理的类没有实现任何接口

// 定义一个业务类,不用实现接口
public class KongmingC {public void buyApple() {System.out.println("孔明得到了苹果...");}
}

定义拦截器,在调用目标方法时,cglib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑

public class CglibProxy implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("超市派二狗子送苹果...");Object result = methodProxy.invokeSuper(o, objects);System.out.println("付款给超市...");return result;}
}

定义动态代理工厂,生成动态代理

public class CglibFactory {// 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现动态代理public static Object getInstaance(Object obj) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(new CglibProxy());return enhancer.create();}
}

客户端调用

public class CglibClient {public static void main(String[] args) {// 调用cglib代理工厂,创建KongmingC 的代理对象KongmingC proxyObj = (KongmingC) CglibFactory.getInstaance(new KongmingC());// 调用代理对象的方法proxyObj.buyApple();}
}
/*  运行结果
超市派二狗子送苹果...
孔明得到了苹果...
付款给超市...
*/
cglib代理的优缺点

优点

  1. 在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
  2. 允许代理的类不实现接口

缺点

  1. 需要额外引入第三方依赖
  2. 因为final修饰的方法不能被重写,所以对于final方法,无法进行代理。

CGLIB动态代理与JDK动态区别

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是通过继承实现代理,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

Spring中代理的运用

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

Java设计模式(五)代理设计模式—静态代理—JDK动态代理—Cglib动态代理相关推荐

  1. Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理

    面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问"茴香豆的茴字有哪几种写法?" 所谓代理模式,是指客户端(Cl ...

  2. Java代理设计模式(Proxy)的具体实现:静态代理和动态代理

    Java代理设计模式(Proxy)的具体实现:静态代理和动态代理 实现方式一:静态代理 静态代理方式的优点 静态代理方式的缺点 Java动态代理实现方式一:InvocationHandler Java ...

  3. Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

    Java之代理... 1 一.         概念... 1 二.         jdk的静态代理... 1 三.         jdk动态代理... 4 四.         cglib 动态 ...

  4. Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理

    前言 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 很多人至今都是看到 代理就懵, 静态代理.动态代理.JDK动态代理.CGL ...

  5. final类是否可以被代理_浅谈Java【代理设计模式】——看这篇文章就懂了

    什么是代理模式 为其他对象提供一种代理以控制对这个对象的访问. 为什么使用代理模式 中介隔离:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的 ...

  6. Java提高班(六)反射和动态代理(JDK Proxy和Cglib)

    反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...

  7. 静态代理,JDK动态代理,Cglib动态代理详解

    目录 一.代理模式 二.静态代理 三.动态代理 3.1 JDK动态代理 3.2 Cglib动态代理 四.两种动态代理区别 一.代理模式 代理模式(Proxy Pattern)是程序设计中的一种设计模式 ...

  8. 浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP面向切面编程的尝试

    文章目录 Java的静态代理 静态代理的优缺点 ABAP的静态代理 Spring AOP的动态代理 JDK动态代理的优缺点 CGLIB动态代理的优缺点 ABAP CGLIB的模拟实现 ABAP Pre ...

  9. Java设计模式 --- 七大常用设计模式示例归纳

    设计模式分为三种类型,共23种: 创建型模式:单例模式.抽象工厂模式.建造者模式.工厂模式.原型模式 结构型模式:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式 行为型模式:模 ...

  10. 【2022最新Java面试宝典】—— 设计模式面试题(14道含答案)

    目录 1.什么是设计模式 2.为什么要学习设计模式 3.设计模式分类 4.设计模式的六大原则 5.单例模式 1.什么是单例 2.那些地方用到了单例模式 3.单例优缺点 4.单例模式使用注意事项: 5. ...

最新文章

  1. 什么样的显卡能支持 4K 分辨率输出?
  2. python和c++哪个好用-python和C++语言哪个好?老男孩教育
  3. centos6.4 安装 mysql_CentOS6.4 安装MySQL
  4. PLSQL 执行 for update 语句被锁定的解决办法
  5. 【目标分类_长尾分布问题】BBN:Bilateral-Branch Network _ CVPR2020
  6. 2016-2017-2学期《程序设计与数据结构》教学进程
  7. 再问数据中台 - 数据中台里的数据质量应该如何保障?
  8. nginx配置与常见错误解决方法
  9. 对单个文件禁用arc
  10. 获取当前实例的字段值
  11. html 怎么绘制曲线图,用html5绘制折线图的实例代码_html5教程技巧
  12. 《黑马程序员Android移动应用基础教程》学习笔记(1)
  13. jasypt.jar 1.9.2下载,加密解密
  14. 黑桃符号java怎么打印出来_java入门基础(四)
  15. EastWave应用案例:机箱屏蔽效能仿真
  16. hbuilder配置浏览器 设置编辑器默认浏览器
  17. 杂谈:渐进增强与优雅降级
  18. NoSuchBeanDefinitionException: No bean named 'tDubboServiceImpl' is defined 的解决办法
  19. 联通云服务器如何开放端口
  20. 微软免费服务器申请教程,2019年8月13日最新免费申请微软OneDrive5TB云盘超详细教程!...

热门文章

  1. vc项目开发:俄罗斯方块制作日志 [上]
  2. 复杂稀缺类分析:稀缺与不重要能否划等号?
  3. 编程小TIPS:使用函数式风格Either来编程
  4. 借助 usb转rs232 模块实现两台电脑文件的传输
  5. 无人机,diyDrones,3dr,pixhawk,Chris Anderson, 这几个概念是什么关系?
  6. 【练习记录】C语言实现正则表达式匹配
  7. PDPS软件:机器人TCP轨迹跟踪功能介绍与使用方法
  8. ShaderGraph节点——UV
  9. spreadsheet php,关于 PhpSpreadsheet 简单教程
  10. python的cfg是什么模块_python操作cfg配置文件方式