附:2种实现方式详细对比 Java 动态代理原理图解( 二 )


CGLib 动态代理实现CGLIB (Code Generation Library) 是一个基于 ASM 的字节码生成库,它允许我们在运行时对字节码进行修改、和动态生成 CGLIB 通过继承方式实现代理 。

附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
在使用 CGLib 之前,我们要先在项目中引入 CGLib 框架 , 在 pom.xml 中添加如下配置:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>
附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
CGLib 的实现代码:
package com.mikechen.proxydemo; import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CGLibExample { static class Car {public void running() {System.out.println("The car is running.");}} /*** CGLib 代理类*/static class CGLibProxy implements MethodInterceptor {private Object target; // 代理对象 public Object getInstance(Object target) {this.target = target;Enhancer enhancer = new Enhancer();// 设置父类为实例类enhancer.setSuperclass(this.target.getClass());// 回调方法enhancer.setCallback(this);// 创建代理对象return enhancer.create();} @Overridepublic Object intercept(Object o, Method method,Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("方法调用前业务处理.");Object result = methodProxy.invokeSuper(o, objects); // 执行方法调用return result;}} // 执行 CGLib 的方法调用public static void main(String[] args) {// 创建 CGLib 代理类CGLibProxy proxy = new CGLibProxy();// 初始化代理对象Car car = (Car) proxy.getInstance(new Car());// 执行方法car.running();
附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
以上程序的执行结果是:
方法调用前业务处理 。
The car is running.
附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
附:2种实现方式详细对比 Java 动态代理原理图解

文章插图
可以看出:
CGLib 和 JDK Proxy 的实现代码比较类似,都是通过实现代理器的接口,再调用某一个方法完成动态代理的 。
唯一不同的是,CGLib 在初始化被代理类时,是通过 Enhancer 对象把代理对象设置为被代理类的子类,来实现动态代理的 。
因此 , 被代理类不能被关键字 final 修饰,如果被 final 修饰,再使用 Enhancer 设置父类时会报错 , 动态代理的构建会失败 。
JDK 动态代理与 CGLib 的区别1.  JDK 动态代理具体实现原理
  • 通过实现 InvocationHandler 接口,创建自己的调用处理器;
  • 通过为 Proxy 类指定 ClassLoader 对象和一组 interface  , 来创建动态代理;
  • 通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入 。
2.  CGLib 动态代理
CGLib 是一个强大、高性能的 Code 生产类库,可以实现运行期动态扩展 java 类,Spring 在运行期间通过 CGlib 继承要被动态代理的类 , 重写父类的方法,实现 AOP 面向切面编程 。
3.  两者对比
  • JDK 动态代理是面向接口的 。
  • CGLib 动态代理是通过字节码底层继承要代理类来实现(如果被代理类被 final 关键字所修饰 , 会失败) 。
4.  性能对比
  • CGLib 所创建的动态代理对象,在实际运行时候的性能要比 JDK 动态代理高不少,有研究表明,大概要高出10倍;
  • CGLib 在创建对象的时候所花费的时间,比 JDK 动态代理要多很多,有研究表明,大概要高出8倍 。
因此,对于 singleton 的代理对象或者具有实例池的代理,因为无需频繁的创建代理对象,更适合采用 CGLib 动态代理,反之,则比较适用 JDK 动态代理 。
【附:2种实现方式详细对比 Java 动态代理原理图解】以上,是关于 Java 动态代理原理、以及动态代理2 种实现方式的解析 。

推荐阅读