动态代理(二)—— CGLIB代理原理

前篇文章动态代理(一)——JDK中的动态代理中详细介绍了JDK动态代理的Demo实现,api介绍,原理详解。这篇文章继续讨论Java中的动态代理,并提及了Java中动态代理的几种实现方式。这里继续介绍CGLIB代理方式。

CGLIB动态代理在AOP、RPC中都有所使用,是Java体系中至关重要的一块内容。本篇文章的主要目标:

  • 掌握使用CGLIB生成代理类
  • 深入理解CGLIB的代理原理

从以上目标出发,本篇文章主要从以下几个方面逐步深入探索CGLIB:

  • CGLIB的使用Demo
  • CGLIB重要API介绍
  • CGLIB代理原理
  • 总结

一.CGLIB的使用Demo

使用CGLIB的大致分为四步骤:

  1. 创建被代理对象
  2. 创建方法拦截器
  3. 创建代理对象
  4. 调用代理对象
1.创建被代理对象
public class EchoServiceImpl implements EchoService {

    public void echo(String message) {
        System.out.println(message);
    }

    public void print(String message) {
        System.out.println(message);
    }

    public int test() {
        return 1;
    }

    public final void finalTest() {
        System.out.println("I am final method.");
    }
}
2.创建方法拦截器
public class EchoServiceInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before invoking!");
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("after invoking!");
        return object;
    }
}

接口MethodInterceptor是CGLIB库提供,用于应用开发者根据自己的业务逻辑进行扩展实现。

3.创建代理对象
//Enhancer是生成代理类的工厂
Enhancer enhancer = new Enhancer();
//设置代理的超类,即被代理对象
enhancer.setSuperclass(EchoServiceImpl.class);
//设置拦截方法
enhancer.setCallback(new EchoServiceInterceptor());
//生成代理对象
EchoService echoService = (EchoService) enhancer.create();
4.调用代理对象
echoService.echo("test");

执行结果:
before invoking!
test
after invoking!

二.CGLIB重要API介绍

CGLIB库的体积很小,但是学习难度确非常高,毕竟涉及到bytecode。所以该篇文章后续关于原理介绍,只涉及代理原理方面,关于如何生成代理对象的方面,由于个人能力所及,不敢妄加说明。

下面是CGLIB的包结构,每个包都是负责一个模块功能,定义非常明确,负责单一的功能职责:

  • net.sf.cglib.core
    低级别的字节码操作的类,它们直接与ASM相关

  • net.sf.cglib.transform
    在运行或者构建时转换类文件的一些类

  • net.sf.cglib.proxy
    创建代理和方法拦截器定义的类

  • net.sf.cglib.reflect
    实现快速反射的一些基础类

  • net.sf.cglib.util
    用于集合排序的一些工具类

  • net.sf.cglib.beans
    与JavaBean相关的类

虽然cglib包含了如此多的功能模块,但是对于使用者,我们并不需要关注如此多的细节,只需要掌握几个重要的接口:

在看完上面的Demo,应该对Enhancer有一定了解。Enhancer字面义即增强,也正如其表述,Enhancer就是用来创建代理对象的接口。其中create方法可以生成代理对象,实际就是工厂模式。

在生成对象前,需要做关于代理方面的配置:

  • 配置被代理对象(目标),即setSuperClass设置超类型,该superClass即Enhancer中持有的Class对象;
  • 配置统一拦截方法(中间人),即setCallBack设置回调接口,对应上图的CallBack。AOP的实现使用methodInterpretor型CallBack;
  • 可选性的配置拦截过滤器(核验流程),即setCallBackFilter,对应上图的CallBackFiler;

Enhancer的create api提供了生成代理对象的。以上即在编写cglib动态代理过程中使用的几个重要api。虽然字节码技术是非常晦涩深奥,但是cglib以简单易用的api使字节码增强技术变得非常容易上手。

通过以上的demo示例和几个重要api的介绍应该都能掌握使用cglib库生成代理类。下面依然通过反编译的方式继续深入cglib的动态代理的调用原理。

三.CGLIB代理原理

1.整体架构与调用过程概览

在详细查看被代理对象的原理之前,先了解下cglib的整体架构图:

从图中可以看出,cglib在字节码层面的操作技术主要依赖ASM提供的能力。在上节中提到的net.sf.cglib.core包,正是与ASM相关。CGLIB上层直接面向应用层,将深奥晦涩的字节码技术包装成应用易用能理解的api,为aop,dynaminc proxy等技术提供了实现基础。

在反编译看代理对象的源代码之前,先看下代理调用的过程图:

从图中可以看出:

  1. 客户端调用代理对象的被代理方法
  2. 代理对象将调用委派给方法拦截器统一接口intercept
  3. 方法拦截器中执行前置操作,然后调用方法代理的统一接口invokeSuper
  4. 方法代理的invokeSuper初始化代理对象的和被代理对象的fastClass
  5. 初始化后,再调用代理对象的fastClass
  6. 代理对象的fastClass能够fast的调用代理的代理对象
  7. 代理对象再调用被代理对象的被代理方法
  8. 调用栈弹出,到intercept中再执行后置操作,方法调用结束

通过以上的过程再来看下它们之间的UML:

在Enhancer中的配置的被代理对象、统一回调的最终都被聚合到生成的代理对象中。(工厂模式,零件组装成产品)
代理对象聚合同一方法回调、继承被代理对象,聚合方法代理的。

2.反编译代理类字节码

CGLIB提供生成代理类的class文件的配置项。在CGLIB中提供了DebuggingClassWriter类用于将字节码的byte字节写入class文件中。

public byte[] toByteArray() {
    
  return (byte[]) java.security.AccessController.doPrivileged(
    new java.security.PrivilegedAction() {
        public Object run() {
            
            // 获取代理类的字节内容
            byte[] b = ((ClassWriter) DebuggingClassWriter.super.cv).toByteArray();
            if (debugLocation != null) {
                    // 转换生成的class文件路径分隔符
                String dirs = className.replace('.', File.separatorChar);
                try {
                     // 创建class文件
                    new File(debugLocation + File.separatorChar + dirs).getParentFile().mkdirs();
                    
                    File file = new File(new File(debugLocation), dirs + ".class");
                    OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                    try {
                         // 将字节内容写入class文件
                        out.write(b);
                    } finally {
                        out.close();
                    }
                    
                    if (traceCtor != null) {
                        file = new File(new File(debugLocation), dirs + ".asm");
                        out = new BufferedOutputStream(new FileOutputStream(file));
                        try {
                            ClassReader cr = new ClassReader(b);
                            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
                            ClassVisitor tcv = (ClassVisitor)traceCtor.newInstance(new Object[]{null, pw});
                            cr.accept(tcv, 0);
                            pw.flush();
                        } finally {
                            out.close();
                        }
                    }
                } catch (Exception e) {
                    throw new CodeGenerationException(e);
                }
            }
            return b;
         }  
        });
        
    }

从以上可以看出只要配置文件的生成路径变量debugLocation即可,再来看下该变量初始化赋值情况

static {
      // 从System中取出属性DEBUG_LOCATION_PROPERTY赋值给文件class文件生成路径变量
    debugLocation = System.getProperty(DEBUG_LOCATION_PROPERTY);
    if (debugLocation != null) {
        System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");
        try {
          Class clazz = Class.forName("org.objectweb.asm.util.TraceClassVisitor");
          traceCtor = clazz.getConstructor(new Class[]{ClassVisitor.class, PrintWriter.class});
        } catch (Throwable ignore) {
        }
    }
}

可以看出只要应用启动时

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,
    "/Users/lixinyou/Documents/code-space/java/java-base/java-proxy/target/proxy/impl");

设置DebuggingClassWriter.DEBUG_LOCATION_PROPERTY属性,在运行时CGLIB便会生成代理类的class。

这种方式与JDK的动态代理中的class文件生成方式一致。这种用法,在日常应用开发中也可借鉴,利用应用启动参数的不同,可以在运行时改变行为,代码具有强扩展性。

3.fastClass机制

在看代理机制源码之前,做好一切准备。再来了解下CGLIB中关于实现快速调用的fastClass机制。
在JDK的动态代理中使用反射调用目标对象,在CGLIB中为了更好的提升性能,采用fastClass机制。

FastClass机制:将类的方法信息解析出来,然后为其建立索引。调用的时候,只要传索引,就能找到相应的方法进行调用。

  1. 为所有的方法建立索引
  2. 调用前先根据方法信息寻找到索引
  3. 调用时根据索匹配相应的方法进行直接调用

CGLIB在字节码层面将方法和索引的对应关系建立,避免了反射调用:

public int getIndex(Signature var1) {
    String var10000 = var1.toString();
    switch(var10000.hashCode()) {
        case -2055565910:
            if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                return 11;
            }
            break;
        case -1980342926:
            if (var10000.equals("print(Ljava/lang/String;)V")) {
                return 6;
            }
            break;
        case -1860420502:
            if (var10000.equals("CGLIB$clone$7()Ljava/lang/Object;")) {
            return 24;
            }
            break;
        case -1725733088:
            if (var10000.equals("getClass()Ljava/lang/Class;")) {
                return 29;
            }
            break;
}
return -1;

}

上述获取方法的索引,下述代码再根据索引进行调用:

public Object invoke(int index, Object var2, Object[] var3) throws InvocationTargetException {
    e77dd5ce var10000 = (e77dd5ce)var2;
    try {
        switch(index) {
        case 0:
            return new Boolean(var10000.equals(var3[0]));
        case 1:
            return var10000.toString();
   } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }
    throw new IllegalArgumentException("Cannot find matching method/constructor");
}
4.运行时的代理类

CGLIB运行时,实际会生成三个class:

  • 代理类
  • 代理类对应的fastClass
  • 被代理类的fastClass

如上述Demo中生成的代理类和相应的代理类:

  1. EchoServiceImpl$$EnhancerByCGLIB$$e77dd5ce$$FastClassByCGLIB$$1b37f797.class
  2. EchoServiceImpl$$EnhancerByCGLIB$$e77dd5ce.class
  3. EchoServiceImpl$$FastClassByCGLIB$$44f86581.class

下面就看下生成的类的代码片段,理解下CGLIB的运行时代理原理。

首先看下生成的代理类

public class EchoServiceImpl$$EnhancerByCGLIB$$e77dd5ce extends EchoServiceImpl implements Factory {

代理类是继承自被代理类,这里与JDK的不同是,JDK是实现了接口。

下面的即是对echo方法的代理方法:

public final void echo(String var1) {
    // 获取方法拦截器
    MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
    if (this.CGLIB$CALLBACK_0 == null) {
        CGLIB$BIND_CALLBACKS(this);
        var10000 = this.CGLIB$CALLBACK_0;
    }

    if (var10000 != null) { // 如果不为空,则调用其统一拦截
        var10000.intercept(this, CGLIB$echo$2$Method, new Object[]{var1}, CGLIB$echo$2$Proxy);
    } else { // 如果为空,则直接调用父类即被代理类的方法
        super.echo(var1);
    }
}

最为让人关注的是intercept方法调用时的参数MethodProxy:CGLIB$echo$2$Proxy

static {
    CGLIB$STATICHOOK1();
}

static void CGLIB$STATICHOOK1() {
    CGLIB$echo$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "echo", "CGLIB$echo$2");
}

在代理类被加载时,执行静态方法CGLIB$STATICHOOK1(),创建了echo方法对应的方法代理。

public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
    MethodProxy proxy = new MethodProxy();
    proxy.sig1 = new Signature(name1, desc);
    proxy.sig2 = new Signature(name2, desc);
    proxy.createInfo = new CreateInfo(c1, c2);
    return proxy;
}

这里使用了工厂模式,在创建MethodProxy时,为期成员CreateInfo赋值。c1代表被代理类,c2代表代理类。desc代理方法和被代理方法的参数信息,name1是被代理方法名,name2是代理方法名。

下面再看来下intercepte方法中调用的methodProxy的invokeSuper方法:

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
        // 先进行初始化
        init();
        // 获取fastClassInfo对象
        FastClassInfo fci = fastClassInfo;
        // 获取代理类对应的fastClass对象并按索引调用
        return fci.f2.invoke(fci.i2, obj, args);
    } catch (InvocationTargetException e) {
        throw e.getTargetException();
    }
}

先看下初始化中所执行的逻辑:

private void init()
{
    /* 
     * Using a volatile invariant allows us to initialize the FastClass and
     * method index pairs atomically.
     * 
     * Double-checked locking is safe with volatile in Java 5.  Before 1.5 this 
     * code could allow fastClassInfo to be instantiated more than once, which
     * appears to be benign.
     */
    if (fastClassInfo == null)
    {
        synchronized (initLock)
        {
            if (fastClassInfo == null)
            {
                CreateInfo ci = createInfo;

                FastClassInfo fci = new FastClassInfo();
                // 获取被代理类
                fci.f1 = helper(ci, ci.c1);
                // 获取代理类
                fci.f2 = helper(ci, ci.c2);
                // 获取被代理类的被代理方法的索引
                fci.i1 = fci.f1.getIndex(sig1);
                // 获取代理类的代理方法的索引
                fci.i2 = fci.f2.getIndex(sig2);
                fastClassInfo = fci;
                createInfo = null;
            }
        }
    }
}

这里使用了单例模式,fastClassInfo对象是单例。所以初始化方法只会在第一次调用代理方法的时候,才响应的进行对其初始化。

初始化后,就将代理类和代理方法的索引获取到了,然后再按照索引直接对代理方法进行调用:

public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
    e77dd5ce var10000 = (e77dd5ce)var2;
    int var10001 = var1;

    try {
        switch(var10001) {
        case 19:
            var10000.CGLIB$echo$2((String)var3[0]);
            return null;
        }
    } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }
    throw new IllegalArgumentException("Cannot find matching method/constructor");
}

上述考虑到篇幅和简洁的原因,这里只摘取了case:19的代码片段。

通过索引直接调用代理类代理方法:CGLIB$echo$2:

final void CGLIB$echo$2(String var1) {
    super.echo(var1);
}

在该方法中再调用被代理类(继承了被代理类)的被代理方法。

至此,CGLIB的代理调用原理就是以上的内容。

四.总结

CGLIB是一种字节码增强库,利用其提供的字节码技术可以实现动态代理。其底层依赖ASM字节码技术。

CGLIB的动态代理与JDK动态代理的不同点:

  • JDK动态代理必须需要接口,JDK代理是基于接口进行动态代理。CGLIB中既支持对接口的代理,也支持对对象的代理。
  • CGLIB动态代理使用fastClass机制实现快速调用被代理类,JDK中使用了反射方式调用被代理。所以CGLIB的动态代理的方式性能上更有优势。
  • CGLIB额外对来源于Object中的finalize和clone方法也做了拦截代理,JDK只为了equals、hashCode、toString进行代理

注:JDK中生成的代理类已经静态解析了方法对象作为代理类的静态变量,类似做缓存,从而部分解决反射的性能问题。

CGLIB的动态代理与JDK动态代理的相同点:

  • 都具有统一接口,JDK动态代理中中间统一接口是InvocationHandler,CGLIB中是MethodInteceptor。
  • 生成的代理类和其中的方法都是final
参考

neoremind/dynamic-proxy
Are there alternatives to cglib
Spring AOP 实现原理与 CGLIB 应用
深入浅出CGlib-打造无入侵的类代理
CGLib: The Missing Manual
Create Proxies Dynamically Using CGLIB Library

转载于:https://www.cnblogs.com/lxyit/p/9328294.html

cglib生成的代理class cglib生成的代理的class 立即下载

相关推荐

实测对比:DJI O3、Walksnail Avatar、HDZero三大高清图传,谁才是低延迟王者?

本文对DJI O3、Walksnail Avatar V2和HDZero三大高清图传系统进行了实测对比,重点分析其在FPV飞行中的低延迟表现。通过专业测试环境和量化数据,揭示HDZero在原生低延迟架构上的优势,DJI O3在画质与延迟间的平衡,以及Walksnail的动态码率调整特点,为不同场景下的选购提供决策依据。

weixin_30756499的博客 429

CGLIB动态代理源码分析

CGLIB动态代理简单案例源码分析大概流程cglib动态代理涉及到的主要类MethodInterceptor.javaEnhancer.javaAbstractClassGenerator.javaDebuggingClassWriter.java cglib动态代理通过实现子类的方式对目标类进行增强。 简单案例 1. 首先建一个目标类Dao public class Dao { ...

yu_kang的博客 3029

深度解读扫地机器人的导航原理

科技改变生活,不可否认科技的进步的确为我们的生活带来许多便捷,以智能家电为例,智能电饭煲、智能洗碗机、智能扫地机等产品已逐渐成为家庭的一分子,其中以扫地机表现最为抢眼。能做到智能规划清扫,收割了不少家庭主妇及科技爱好者的芳心。但扫地机并非一开始就这么智能,最初的扫地机只能做到随机式清扫,会频繁出现碰撞现象。 近年来,通过业界的不断努力,目前,扫地机器人已告别乱碰乱撞现象,能做到自主路径...

qq_38403231的博客 6496

踩坑日记:引入CGlib动态代理jar包,报错“ org/objectweb/asm/util/TraceClassVisitor”

Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/util/TraceClassVisitor 这个问题,是引入jar包的时候,我引入的版本是3.0,然后报错了,我换成了3.3.0就好了。 我们可以去cglib的github上去看看它发布的版本,找一个最新的。 不行 话就挨个试试,因为具体的版本和asm的版本也许会有冲突,我没有引入asm,直接引入的cglib的jar包,就可以用了。

好学而不勤问非真好学者 683

MacOS多次踩坑后成功安装Homebrew

来一次性成功安装Homebrew吧 官网提供的安装脚本无法成功安装Homebrew,原因大家都懂的,故采用脚本安装的方式。 下载homebrew的安装脚本brew_install 在Download路径下执行如下脚本 curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install >> brew_install 修改brew_install脚本 修改brew_install脚本。如果你的脚本打开之后是如下

weixin_41847116的博客 1978

MRI脑影像分析从哲学到技术:一文搞懂VBM预处理基本原理(全网最详细解析)

   分析大脑解剖学差异最常用方法之一是基于体素的形态学方法(voxel-based morphometry, VBM)。 VBM的基本思想是测量大脑组织,尤其是灰质的局部浓度的差异。在大脑的每个体素处进行操作,然后在两个或多个实验组之间进行统计比较,从而在受调查的组之间建立特定大脑区域中脑组织浓度的统计学显着差异。 VBM分析基于(高分辨率)MRI脑部扫描,涉及大量处理步骤,主要是空间归一化,分割,平滑和统计分析,最终结果是统计图,显示了各组之间组织类型明显不同的区域[^1]。 参考 [^1] ..

意疏的学习笔记 3万+

cglib代理解析

/

一个菜鸟的博客 771

Android14 有线网络静态IP配置:从固件烧录到系统默认设置

本文详细解析了在Android14系统中,如何通过修改系统框架层和设置应用,为设备预设有线网络静态IP地址,实现固件烧录后即具备指定网络配置的功能。文章深入探讨了从扩展SettingsProvider数据库字段、配置默认值,到在设置应用中读取和应用配置的完整流程,旨在解决工业平板、智能终端等设备在无DHCP网络环境中批量部署的痛点,提升开箱即用体验。

lake5的博客 914

spring test如何设置DebuggingClassWriter.DEBUG_LOCATION_PROPERTY

有时我们想要查看项目中产生的cglib动态类,我们可以通过下面的方法设置: System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "导出的类文件目录"); 但是我们需要知道的一点就是cglib类是在运行时产生的,如果到了下面的方法再去设置DebuggingClassWriter.DEBUG_LOCATION_PROPE...

johnhuster的专栏 2006

告别Keil?在Mac上配置STM32CubeIDE + CMSIS-DAP调试器全攻略(含常见报错解决)

本文详细介绍了在Mac平台上配置STM32CubeIDE与CMSIS-DAP调试器的全流程,包括硬件准备、软件安装、工程创建及调试优化。通过实战指南,帮助开发者高效完成STM32开发,解决常见报错问题,提升开发效率。

weixin_30485379的博客 422

雾化器硬件设计:从N155驱动到PCB可量产实现

雾化器是典型的机电一体化嵌入式终端,其硬件设计本质是电源完整性、信号完整性与热-机械协同的系统工程。核心在于理解高压脉冲驱动原理(如2.4MHz固定频率匹配压电谐振)、电源域隔离机制(AGND/DGND/PGND分域设计)及约束驱动的PCB转化逻辑。技术价值体现在电气可靠性(如OTP/OLP保护)、生产可制造性(DFM合规焊盘与钢网)与环境鲁棒性(三防漆、散热过孔)。典型应用场景覆盖加湿器、医疗雾化仪与工业微流控设备。本文聚焦超声波雾化控制板的硬线实现路径,深入解析N155驱动芯片选型、网络标签工程误用陷阱

weixin_35649491的博客 607

【动态代理】CGLIB 动态代理的使用及原理

JDK 的中动态代理类位于 java.lang.reflect 包下,一般主要涉及到以下两个类:

sco5282的博客 1万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

动态代理原理解析 (二):cglib

面对没有接口的类,可以使用基于cglib的动态代理,对于final方法无法代理。 cglib的底层是使用字节码处理框架asm操纵字节码生成代理类,操纵的级别是底层JVM的汇编指令级别。 使用案例: <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2&l

qq_45756124的博客 364

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

AOP实现原理(二)CGLIB动态代理

上一篇博客中给大家介绍了AOP中的JDK动态代理。附上地址: https://blog.csdn.net/bicheng4769/article/details/80028158 回顾一下上一篇的内容,JDK动态代理必须要求目标类实现接口才能使用。那么在AOP的使用中,我们貌似没有这个限制,所以这里AOP还有一种动态代理的机制:CGLIB动态代理。 什么是CGLIB CGLIB(Co...

我是你妹她哥的博客 3558

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

理解Spring AOP 原理(二)JDK,CGLIB动态代理以及ProxyFactory

Spring AOP的底层是基于JDK和CGLIB代理技术来实现的,要理解Spring AOP,需要先对JDK和CGLIB有一定的认识和理解。一. JDK动态代理先看一段Demo示例,首先定义一个接口:public interface DemoInterface { public void service(); }该接口的实现:public class DemoImpl implements

liuxiang87的专栏 958

JAVA基础:动态代理cglib原理(二)Fastclass 机制分析

JDK动态代理的拦截对象是通过反射的机制来调用被拦截方法的,反射的效率比较低,所以CGLIB采用了FastClass的机制来实现对被拦截方法的调用。

qq_38940885的博客 2069

【Spring源码:AOP二】基于JDK动态代理和Cglib创建代理对象的原理分析

上一篇,我们最后通过一个例子讲解了resolveBeforeInstantiation()中,通过InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation返回一个代理对象,下面,我们继续分析这个方法返回的是null的情况,那么它就会往下执行doCreateBean()。 @Override protected Object createBean(String beanName, RootBeanDefinition mbd,

骏马逸动,心随你动的博客 356

Spring面向切面编程(AOP)原理二之使用Cglib实现动态代理

上面我们已经介绍了使用JDK实现动态代理的过程 Spring面向切面编程(AOP)原理一之使用JDK实现动态代理 除了可以使用JDK实现动态代理之外,还可以使用Cglib实现动态代理。 在Spring框架内部的AOP(面向切面编程)就是会自动切换JDK和Cglib实现动态代理。 上面已经介绍了JDK使用条件是必须要有接口,但是Cglib就没有这个条件。 Cglib是第三方平台的,所以使用之前需要导...

shijiujiu33的博客 724

Cglib Dynamic Proxy(Cglib 动态代理)

使用JDK创建动态代理只能为接口创建代理实例,这第一点从Proxy的接口签名newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)中就可以看的很清楚:第二个入参interfaces就是需要代理实例的接口列表。对于没有接口定义的业务方法的类,则使用Cglib动态代理。          Cglib采用了非

alex_sym的专栏 909

Spring5学习总结(二)AOP底层原理JDK动态代理CGLIB动态代理AOP术语切入点表达式基于xml配置文件实现AOP操作基于注解实现AOP操作五种通知的实现完全注解开发

在软件业,AOP为面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。通俗描述:不通过修改源代码的方式实现在主干功能里面添加新功能(例如我想增强已写好的登录功能,不去修改已有的登录代码,而是使用AOP增强)

long3359的博客 244

JDK动态代理、Cglib动态代理及Spring AOP

Java中的JDK动态代理是一种通过反射机制生成代理对象的技术,使得我们能够在运行时动态地创建某个接口的代理类,而无需手动编写实现类。JDK动态代理通常用于横切关注点(如日志、事务管理、安全性等)在方法调用前后进行处理,而不需要修改目标类的源代码。

意疏的博客 6380

动态代理之 cglib 实现

(尊重劳动成果,转载请注明出处:https://blog.csdn.net/qq_25827845/article/details/87513102冷血之心的博客) 目录 前言: 正文: AOP(面向切面编程) JDK动态代理 cglib实现动态代理 cglib包结构: cglib动态代理相关的基础类: cglib动态代理Demo 总结: 前言:         这篇文...

冷血之心的博客 9282

cglib动态代理

CGLIB(Code Generation Library),是一个强大的,高性能,高质量的 Code 生成类库,它可以在运行期扩展 Java 类与实现 Java 接口。

NCS123456的博客 1万+

Java动态代理与CGLIB动态代理实现原理

动态代理是 AOP(Aspect Orient Programming)编程思想,理解动态代理原理,对学习AOP框架至关重要。 JDK动态代理不需要任何外部依赖,但是只能基于接口进行代理;CGLIB通过继承的方式进行代理,无论目标对象有没有实现接口都可以代理,但是无法代理final对象与final方法。(final类型不能有子类,final方法不能被重载)

write6的专栏 2932

JDK动态代理和CGLIB动态代理有什么区别?

JDK动态代理和CGLIB动态代理有什么区别?

水w的博客 8005
上一篇: iOS 点击推送消息跳转指定界面 —总结篇
下一篇: LeetCode 394. Decode String
weixin_34269583
博客等级 码龄11年 6474粉丝 1280原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值