CGlib实现原理详解

一、CGlib代理原理

在面向对象编程中,代理模式是一种常用的设计模式。它可以在不改变原有对象代码的前提下,通过新增代理对象,在代理对象中增加一些其他的功能,从而提供更加完整、更加复杂的功能。CGlib代理是基于动态代理的一种实现方式,是Java中常用的代理技术之一。

动态代理和静态代理最大的区别就在于代理类的生成方式。静态代理需要人工编写代理类,而动态代理则可以在运行时动态生成代理类。Java JDK提供了一个Proxy类,可以通过Proxy的工厂方法newProxyInstance动态生成代理对象。

不过JDK提供的动态代理有一个限制,就是只能代理实现了接口的类。如果要代理没有实现接口的类,就要使用其他的代理技术。而CGlib是一种可以代理类的技术。使用CGlib实现动态代理,本质上是在运行时,通过字节码处理框架ASM,动态生成一个被代理类的子类,并覆盖其中的方法,达到代理的目的。

二、CGlib原理

CGlib,全称为Code Generation Library,是一个开源的非侵入式的Java字节码生成库。它允许在运行时对字节码进行操作,生成新的类,以实现例如AOP之类的功能。

与静态代理和JDK动态代理不同,CGlib在运行时动态生成被代理类的子类,并重写其中的方法。因此,对被代理类的方法访问是通过子类方法访问的,而不是被代理类方法访问的。子类方法可以通过调用父类方法实现对被代理类方法的访问。

CGlib生成子代理类的方式是在内存中构建代理类的所有方法的字节码,并将其转换成class对象,从而实现对被代理类方法的代理。由于CGlib是直接操作class字节码实现代理的,因此需要引入ASM字节码框架,用于处理Java字节码。

三、CGlib底层原理

CGlib底层运用Java字节码技术实现代理,下面简单介绍一下Java字节码的执行过程:

一是Java程序源代码被编译成Java字节码文件(.class文件)。

二是Java虚拟机(JVM)将Java字节码文件解释成机器指令。

三是CPU执行机器指令,进行计算操作。

CGlib底层实现通过ASM技术直接操作字节码来完成对代理对象的生成,主要分为以下几个步骤:

1、确定需要代理的类和方法,生成对应的MethodInterceptor实现类。

public class UserProxy implements MethodInterceptor {
    private Object target;
    public UserProxy(Object target) {
        this.target = target;
    }
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invoke");
        Object result = method.invoke(target, args);
        System.out.println("After method invoke");
        return result;
    }
}

2、使用ASM库加载被代理类的字节码,并动态生成代理对象的子类。

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new UserProxy(target));
Object proxy = enhancer.create();

在这个过程中,我们需要在内存中先读取被代理类的二进制字节码文件,然后再解析出类信息,这个时候我们就要使用ASM库:

ClassReader classReader = new ClassReader(target.getClass().getName());
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor = new AddFieldAdapter(classWriter,
                Opcodes.ACC_PUBLIC, "hash", "I");
classReader.accept(classVisitor, ClassReader.SKIP_DEBUG);
byte[] data = classWriter.toByteArray();

四、CGlib底层实现原理

底层实现原理主要是通过ASM(a very small and fast Java bytecode manipulation framework)框架来直接操作数据字节码。ASM可以直接生成和修改字节码,也可以在字节码的生成和修改中提供一些帮助和支持。

ASM使用Visitor模式来操作字节码,它通过ClassVisitor和MethodVisitor类提供了访问类层次结构和方法级别元素的途径。

CGlib实现动态代理的过程如下:

1、创建Enhancer对象。

2、设置父类和回调方法。

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new UserServiceInterceptor());

3、通过Enhancer对象的create()方法生成代理对象。

UserServiceImpl proxyUserService = (UserServiceImpl) enhancer.create();

4、调用代理对象方法。

String username = userSerivceimpl.getUserName();

五、CGlib动态代理原理

CGlib可以创建一个类的子类,并且在子类中采用方法拦截的技术拦截所有父类方法的调用。在拦截器中可以添加一些额外的逻辑。相比Java动态代理,CGlib不要求被代理类必须实现接口,它是基于类代理,对指定的类生成一个子类,并覆盖其中的方法来实现代理的功能。

在使用CGlib进行代理时,代理类和被代理类构成了继承关系。代理类继承被代理类,所以代理类拥有了被代理类的所有属性和方法,而且可以拦截被代理方法进行增强。

下面是一个CGlib动态代理实现的示例代码:

public class UserServiceInterceptor implements MethodInterceptor {
    private UserService userService;
    public UserServiceInterceptor(UserService userService) {
        this.userService = userService;
    }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("begin method...");
        Object result = method.invoke(userService, objects);
        System.out.println("end method...");
        return result;
    }
}
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class); 
enhancer.setCallback(new UserServiceInterceptor(userService));
UserService userServiceProxy = (UserService) enhancer.create();

结束语

CGlib是一种非常常用的代理方式,通过字节码的修改,可以实现对被代理对象的增强和功能扩展。在使用CGlib进行代理时,我们需要深入了解其实现原理,灵活运用其底层知识,才能更好地发挥其代理作用。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/307349.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2025-01-02 18:06
下一篇 2025-01-02 18:06

相关推荐

  • Harris角点检测算法原理与实现

    本文将从多个方面对Harris角点检测算法进行详细的阐述,包括算法原理、实现步骤、代码实现等。 一、Harris角点检测算法原理 Harris角点检测算法是一种经典的计算机视觉算法…

    编程 2025-04-29
  • 瘦脸算法 Python 原理与实现

    本文将从多个方面详细阐述瘦脸算法 Python 实现的原理和方法,包括该算法的意义、流程、代码实现、优化等内容。 一、算法意义 随着科技的发展,瘦脸算法已经成为了人们修图中不可缺少…

    编程 2025-04-29
  • 神经网络BP算法原理

    本文将从多个方面对神经网络BP算法原理进行详细阐述,并给出完整的代码示例。 一、BP算法简介 BP算法是一种常用的神经网络训练算法,其全称为反向传播算法。BP算法的基本思想是通过正…

    编程 2025-04-29
  • GloVe词向量:从原理到应用

    本文将从多个方面对GloVe词向量进行详细的阐述,包括其原理、优缺点、应用以及代码实现。如果你对词向量感兴趣,那么这篇文章将会是一次很好的学习体验。 一、原理 GloVe(Glob…

    编程 2025-04-27
  • 编译原理语法分析思维导图

    本文将从以下几个方面详细阐述编译原理语法分析思维导图: 一、语法分析介绍 1.1 语法分析的定义 语法分析是编译器中将输入的字符流转换成抽象语法树的一个过程。该过程的目的是确保输入…

    编程 2025-04-27
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25

发表回复

登录后才能评论