静态代理?动态代理?JDK动态代理和CGLIB包实现动态代理的区别

简介: 什么是静态代理?什么是动态代理?JDK动态代理和CGLIB包实现动态代理的区别

什么是静态代理?什么是动态代理?JDK动态代理和CGLIB包实现动态代理的区别

image.png

一.什么是静态代理?

  1. JVM层面:在编译时就已经实现,编译完成后代理类是一个实际的class文件。
  2. 灵活性:静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,非常麻烦的。

    使用JDK静态代理很容易就完成了对一个类的代理操作。但是JDK静态代理只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较麻烦。

二.什么是动态代理?

  1. JVM层面:在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中。
  2. 灵活性:动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。

三.JDK动态代理和CGLIB包实现动态代理的区别?

3.1 JDK动态代理

3.1.1 JDK动态代理步骤

  1. 通过实现InvocationHandler接口来自定义自己的InvocationHandler;
  2. 通过Proxy.getProxyClass获得动态代理类;
  3. 通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class);
  4. 通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入;
  5. 通过代理对象调用目标方法;

3.1.2 概括静态代理和动态代理区别

  1. JDK静态代理是通过直接编码创建的,JDK动态代理是利用反射机制在运行时创建代理类的。
  2. 具体体现在上面我们从灵活性和JVM层面分析静态代理和动态代理的区别。

3.2 CGLIB包实现动态代理

3.2.1 核心思想

CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。

3.2.2 CGLIB代理步骤

  1. 实现一个MethodInterceptor,方法调用会被转发到该类的intercept()方法。
  2. 然后在需要使用的时候,通过CGLIB动态代理获取代理对象。

3.2.3 CGLIB在进行代理的时候都进行了哪些工作

  1. 生成的代理类继承被代理类。在这里我们需要注意一点:如果委托类被final修饰,那么它不可被继承,即不可被代理;同样,如果委托类中存在final修饰的方法,那么该方法也不可被代理
  2. 代理类会为委托方法生成两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法
  3. 当执行代理对象的方法时,会首先判断一下是否存在实现了MethodInterceptor接口的CGLIB$CALLBACK_0;,如果存在,则将调用MethodInterceptor中的intercept方法,在intercept方法中,我们除了会调用委托方法,还会进行一些增强操作。在Spring AOP中,典型的应用场景就是在某些敏感方法执行前后进行操作日志记录

3.2.4 CGLIB中方法的调用还是通过反射吗?

不是,在CGLIB中,方法的调用并不是通过反射来完成的,而是直接对方法进行调用:通过FastClass机制对Class对象进行特别的处理,CGLIB采用了FastClass的机制来实现对被拦截方法的调用。FastClass机制就是对一个类的方法建立索引,通过索引index来直接调用相应的方法

四.JDK动态代理和CGlib动态代理哪一个更快呢?

  1. 在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率。只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理,总之,每一次jdk版本升级,jdk代理效率都得到提升,而CGLIB代理就有些慢了。
  2. 使用CGLIB实现动态代理,CGLIB底层采用ASM字节码生成框架,使用字节码技术生成代理类, 在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLIB不能对声明为final的方法进行代理, 因为CGLIB原理是动态生成被代理类的子类。

五.Spring如何选择JDK动态代理还是CGLIB动态代理?

  1. 当Bean实现接口时,Spring就会用JDK的动态代理。
  2. 当Bean没有实现接口时,Spring使用CGlib实现。
相关文章
|
4月前
|
Java 编译器 API
【面试问题】JDK 和 JRE 的区别?
【1月更文挑战第27天】【面试问题】JDK 和 JRE 的区别?
|
2月前
|
Java 程序员 API
浅谈JDK动态代理
浅谈JDK动态代理
33 1
|
2月前
|
存储 安全 Java
JDK、JRE 和 JVM 的区别和联系
JDK、JRE 和 JVM 的区别和联系
23 0
|
3月前
|
Java
关于JDK动态代理
关于JDK动态代理的一些理解
14 0
|
3月前
|
设计模式 Java API
[Java]静态代理、动态代理(基于JDK1.8)
本篇文章主要是对静态代理和动态代理实现思路的简述,以示例为主,少涉及理论。 如果文中阐述不全或不对的,多多交流。
54 1
[Java]静态代理、动态代理(基于JDK1.8)
|
3月前
|
设计模式 安全 Java
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
342 1
|
4月前
|
Java 数据安全/隐私保护
【面试问题】JDK 动态代理与 CGLIB 区别?
【1月更文挑战第27天】【面试问题】JDK 动态代理与 CGLIB 区别?
|
1天前
|
弹性计算 运维 Java
一键安装二进制JDK
【4月更文挑战第30天】
6 0
|
2天前
|
关系型数据库 MySQL 应用服务中间件
centos7在线安装jdk1.8+tomcat+mysql8+nginx+docker
现在,你已经成功在CentOS 7上安装了JDK 1.8、Tomcat、MySQL 8、Nginx和Docker。你可以根据需要配置和使用这些服务。请注意,安装和配置这些服务的详细设置取决于你的具体需求。
17 2
|
4天前
|
Java Windows
java——安装JDK及配置解决常见问题
java——安装JDK及配置解决常见问题