cglib源码学习交流

article/2025/10/31 13:17:53

背景

    前段时间在工作中,包括一些代码阅读过程中,spring aop经常性的会看到cglib中的相关内容,包括BeanCopier,BulkBean,Enancher等内容,以前虽大致知道一些内容,原理是通过bytecode,但没具体深入代码研究,只知其所用不知其所以然,所以就特地花了半天多的工作时间研究了CGLIB的相关源码,同时结合看了下 spring Aop中对CGLIB的使用。

    本文主要通过对cglib有原理的分析,反编译查看源码,例子等方式做一个介绍。

cglib基本信息

  1. cglib的官方网站:  http://cglib.sourceforge.net/
  2. cglib目前的最新版本应该是2.2,公司普遍使用的版本也是这个
  3. 官网的samples :  http://cglib.sourceforge.net/xref/samples/

cglib代码包结构

  • core (核心代码)
    • EmitUtils
    • ReflectUtils
    • KeyFactory
    • ClassEmitter/CodeEmitter
    • NamingPolicy/DefaultNamingPolicy
    • GeneratorStrategy/DefaultGeneratorStrategy
    • DebuggingClassWriter
    • ClassGenerator/AbstractClassGenerator
  • beans (bean操作类)
    • BeanCopier
    • BulkBean
    • BeanMap
    • ImmutableBean
    • BeanGenerator
  • reflect
    • FastClass
  • proxy
    • Enhancer
    • CallbackGenerator
    • Callback
      • MethodInterceptor   , Dispatcher, LazyLoader , ProxyRefDispatcher , NoOp , FixedValue , InvocationHandler(提供和jdk proxy的功能)
    • CallbackFilter
  • util
    • StringSwitcher 
    • ParallelSorter 
  • transform 

core核心代码部分

EmitUtils

重要的工具类,主要封装了一些操作bytecode的基本函数,比如生成一个null_constructor,添加类属性add_property等

ReflectUtils

处理jdk reflect的工具类,比如获取一个类所有的Method,获取构造函数信息等。

ClassEmitter/CodeEmitter

对asm的classAdapter和MethodAdapter的实现,贯穿于cglib代码的处理

KeyFactory

类库中重要的唯一标识生成器,用于cglib做cache时做map key,比较底层的基础类。
例子:

interface
BulkBeanKey {
public Object newInstance(String target, String [] getters, String [] setters, String [] types);
}
(BulkBeanKey)KeyFactory.create(BulkBeanKey.class).newInstance(targetClassName, getters, setters, typeClassNames);

说明:

  • 每个Key接口,都必须提供newInstance方法,但具体的参数可以随意定义,通过newInstance返回的为一个唯一标示,只有当传入的所有参数的equals都返回true时,生成的key才是相同的,这就相当于多key的概念。

NamingPolicy

默认的实现类:DefaultNamingPolicy, 具体cglib动态生成类的命名控制。
一般的命名规则:

  • 被代理class name + "$$" + 使用cglib处理的class name + "ByCGLIB" + "$$" + key的hashcode
  • 示例:FastSource $$FastClass ByCGLIB$$e1a36bab.class

GeneratorStrategy

默认的实现类: DefaultGeneratorStrategy
控制ClassGenerator生成class的byte数据,中间可插入自己的处理。注意这里依赖了:DebuggingClassWriter进行class generator的处理

DebuggingClassWriter

cglib封装asm的处理类,用于生成class的byte流,通过GeneratorStrategy回调ClassGenerator.generateClass(DebuggingClassWriter),将自定义的class byte处理回调给具体的cglib上层操作类,比如由具体的BeanCopier去控制bytecode的生成。

ClassGenerator

其中一个抽象实现:AbstractClassGenerator。cglib代码中核心的Class bytecode操作主体,包含了一些cache,调用NamingPolicy,GeneratorStrategy进行处理,可以说是一个最核心的调度者。

 

 

对应的类图:

 

  1. 外部的BeanCopier都包含了一Generator,继承自AbstractClassGenerator,实现了generateClass(ClassVisitor v),Object firstInstance(Class type)方法。
  2. AbstractClassGenerator自身会根据Source进行cache,所以针对已经生成过的class,这里KeyFactory对应的值要相等,则会直接返回cache中的结果。所以BeanCopier每次create慢只是每次都需要new两个对象,一个是KeyFactory.newInstance,另一个是firstInstance方法调用生成一个对象。

反编译tips

大家都知道cglib是进行bytecode操作,会动态生成class,最快最直接的学习就是结合他生成的class,对照代码进行学习,效果会好很多。

Java代码     收藏代码
  1. system.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,  "指定输出目录" );   

 可参见 cores/DebuggingClassWriter代码。说明:这样cglib会将动态生成的每个class都输出到文件中,然后我们可以通过decomp 进行反编译查看源码。

 

beans (相关操作类)

BeanCopier

简单的示例代码就不做介绍,相信大家都指导怎么用,这里主要介绍下Convert的使用。

  • 许多网友都做过BeanCopier,BeanUtils的测试,基本BeanCopier的性能是BeanUtils的10倍以上。 ,出了反射这一性能差异外,BeanUtils默认是开启Converter功能,允许同名,不同类型的属性进行拷贝,比如Date对象到String属性。
  • 有兴趣的同学可以去比较下PropertyUtils,默认不开启Converter功能,发现性能是BeanUtils的2倍多。

初始化例子:BeanCopier copier = BeanCopier.create(Source.class, Target.class, true); 
第三个参数useConverter,是否开启Convert,默认BeanCopier只会做同名,同类型属性的copier,否则就会报错。

Converter使用例子代码     收藏代码
  1. public class BeanCopierTest {  
  2.   
  3.     public static void main(String args[]) {  
  4.         System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/tmp/1" );  
  5.         BeanCopier copier = BeanCopier.create(Source.class, Target.class, true);  
  6.         Source from = new Source();  
  7.         from.setValue(1 );  
  8.   
  9.         Target to = new Target();  
  10.         Converter converter = new BigIntConverter();  
  11.         copier.copy(from, to, converter); //使用converter类  
  12.   
  13.         System.out.println(to.getValue());  
  14.     }  
  15. }  
  16.   
  17. class BigIntConverter implements net.sf.cglib.core.Converter {  
  18.   
  19.     @Override  
  20.     public Object convert(Object value, Class target, Object context) {  
  21.         System.out.println(value.getClass() + " "  + value); // from类中的value对象  
  22.         System.out.println(target); // to类中的定义的参数对象  
  23.         System.out.println(context.getClass() + " "  + context); // String对象,具体的方法名  
  24.         if (target.isAssignableFrom(BigInteger.class)) {  
  25.             return new BigInteger(value.toString());  
  26.         } else {  
  27.             return value;  
  28.         }  
  29.     }  
  30.   
  31. }  
  32. ----  
  33. 反编译后看的代码:  
  34. public class Target$$BeanCopierByCGLIB$$e1c34377 extends BeanCopier  
  35. {  
  36.     public void copy(Object obj, Object obj1, Converter converter)  
  37.     {  
  38.         Target target = (Target)obj1;  
  39.         Source source = (Source)obj;  
  40.         // 注意是直接调用,没有通过reflect  
  41.         target.setValue((BigInteger)converter.convert(new Integer(source.getValue()), CGLIB$load_class$java$2Emath$2EBigInteger, "setValue" ));   
  42.     }  
  43. }  

 

使用注意

  1. 避免每次进行BeanCopier.create创建对象,一般建议是通过static BeanCopier copier = BeanCopier.create()
  2. 合理使用converter。
  3. 应用场景:两个对象之间同名同属性的数据拷贝,  不能单独针对其中的几个属性单独拷贝

BulkBean

     相比于BeanCopier,BulkBean将整个Copy的动作拆分为getPropertyValues,setPropertyValues的两个方法,允许自定义处理的属性。

 

Java代码     收藏代码
  1. public   class  BulkBeanTest {  
  2.   
  3.     public   static   void  main(String args[]) {  
  4.         System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/home/ljh/cglib" );  
  5.         String[] getter = new  String[] {  "getValue"  };  
  6.         String[] setter = new  String[] {  "setValue"  };  
  7.         Class[] clazzs = new  Class[] {  int . class  };  
  8.   
  9.         BulkBean bean = BulkBean.create(BulkSource.class , getter, setter, clazzs);  
  10.         BulkSource obj = new  BulkSource();  
  11.         obj.setValue(1 );  
  12.   
  13.         Object[] objs = bean.getPropertyValues(obj);  
  14.         for  (Object tmp : objs) {  
  15.             System.out.println(tmp);  
  16.         }  
  17.     }  
  18. }  
  19. class  BulkSource {  
  20.     private   int  value;  
  21.     .....  
  22. }  
  23.   
  24. // 反编译后的代码:    
  25.  public   void  getPropertyValues(Object obj, Object aobj[])  
  26.     {  
  27.         BulkSource bulksource = (BulkSource)obj;  
  28.         aobj[0 ] =  new  Integer(bulksource.getValue());  
  29.     }  

 

使用注意

  1. 避免每次进行BulkBean.create创建对象,一般建议是通过static BulkBean.create copier = BulkBean.create
  2. 应用场景:针对特定属性的get,set操作,一般适用通过xml配置注入和注出的属性,运行时才确定处理的Source,Target类,只需关注属性名即可。

 

BeanMap

相比于BeanCopier,BulkBean,都是针对两个Pojo Bean进行处理,那如果对象一个是Pojo Bean和Map对象之间,那就得看看BeanMap,将一个java bean允许通过map的api进行调用。
几个支持的操作接口:

  • Object get(Object key)
  • Object put(Object key, Object value)
  • void putAll(Map t)
  • Set entrySet()
  • Collection values()
  • boolean containsKey(Object key)
  • ....
Java代码     收藏代码
  1. public   class  BeanMapTest {  
  2.   
  3.     public   static   void  main(String args[]) {  
  4.         // 初始化   
  5.         BeanMap map = BeanMap.create(new  Pojo());  
  6.         // 构造   
  7.         Pojo pojo = new  Pojo();  
  8.         pojo.setIntValue(1 );  
  9.         pojo.setBigInteger(new  BigInteger( "2" ));  
  10.         // 赋值   
  11.         map.setBean(pojo);  
  12.         // 验证   
  13.         System.out.println(map.get("intValue" ));  
  14.         System.out.println(map.keySet());  
  15.         System.out.println(map.values());  
  16.     }  
  17. }  
  18.   
  19. class  Pojo {  
  20.   
  21.     private   int         intValue;  
  22.     private  BigInteger bigInteger;  
  23.     ....  
  24. }  
  25.   
  26. //反编译代码查看:   
  27. //首先保存了所有的属性到一个set中   
  28. private   static  FixedKeySet keys =  new  FixedKeySet( new  String[] {  
  29.         "bigInteger" "intValue"   
  30.     });  
  31. public  Object get(Object obj, Object obj1)  
  32.     {  
  33.         (Pojo)obj;  
  34.         String s = (String)obj1;  
  35.         s;  
  36.         s.hashCode();  
  37.         JVM INSTR lookupswitch 2 default   72   
  38.     //                   -139068386: 40   
  39.     //                   556050114: 52;   
  40.            goto  _L1 _L2 _L3  
  41. _L2:  
  42.         "bigInteger" ;  
  43.  //属性判断是否相等   
  44.         equals();  
  45.         JVM INSTR ifeq 73 ;  
  46.            goto  _L4 _L5  
  47. _L5:  
  48.         break  MISSING_BLOCK_LABEL_73;  
  49. _L4:  
  50.         getBigInteger();  
  51.         return ;  
  52. _L3:  
  53.   
  54. ....  
  55.   
  56. }  

 

使用注意

  1. 避免每次进行BeanMap map = BeanMap.create();创建对象,不同于BeanCopier对象,BeanMap主要针对对象实例进行处理,所以一般建议是map.setBean(pojo);进行动态替换持有的对象实例。
  2. 应用场景:针对put,putAll操作会直接修改pojo对象里的属性,所以可以通过beanMap.putAll(map)进行map<->pojo属性的拷贝。

 

BeanGenerator

   暂时没有想到合适的使用场景,不过BeanGenerator使用概念是很简单的,就是将一个Map<String,Class>properties的属性定义,动态生成一个pojo bean类。

 

Java代码     收藏代码
  1. BeanGenerator generator =  new  BeanGenerator();  
  2. generator.addProperty("intValue" int . class );  
  3. generator.addProperty("integer" , Integer. class );  
  4. generator.addProperty("properties" , Properties. class );  
  5.          
  6. Class clazz = (Class) generator.createClass();  
  7. Object obj = generator.create();  
  8.   
  9. PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(obj.getClass());  
  10. for  (PropertyDescriptor getter : getters) {  
  11.     Method write = getter.getWriteMethod();  
  12.     System.out.println(write.getName());  
  13. }  

 

ImmutableBean

bean Immutable模式的一种动态class实现,Immutable模式主要应用于服务设计上,返回的pojo bean对象,不运行进行write方法调用。

 

 

说明

个人是不太建议使用cglib动态class的方式来实现bean Immutable的模式,Immutable模式应该是一种服务接口上的显示声明,而不是如此隐晦,而且pojo bean尽量做到是轻量级,简答的set/get方法,如果要做充血的领域模型那就另当别论了。

 

reflect (class,method处理)

FastClass

顾明思义,FastClass就是对Class对象进行特定的处理,比如通过数组保存method引用,因此FastClass引出了一个index下标的新概念,比如getIndex(String name, Class[] parameterTypes)就是以前的获取method的方法。
通过数组存储method,constructor等class信息,从而将原先的反射调用,转化为class.index的直接调用,从而体现所谓的FastClass。

Java代码     收藏代码
  1. public   class  FastClassTest {  
  2.     public   static   void  main(String args[])  throws  Exception {  
  3.         System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/home/ljh/cglib" );  
  4.   
  5.         FastClass clazz = FastClass.create(FastSource.class );  
  6.         // fast class反射调用   
  7.         FastSource obj = (FastSource) clazz.newInstance();  
  8.         clazz.invoke("setValue" new  Class[] {  int . class  }, obj,  new  Object[] {  1  });  
  9.         clazz.invoke("setOther" new  Class[] {  int . class  }, obj,  new  Object[] {  2  });  
  10.   
  11.         int  value = (Integer) clazz.invoke( "getValue" new  Class[] {}, obj,  new  Object[] {});  
  12.         int  other = (Integer) clazz.invoke( "getOther" new  Class[] {}, obj,  new  Object[] {});  
  13.         System.out.println(value + " "  + other);  
  14.         // fastMethod使用   
  15.         FastMethod setValue = clazz.getMethod("setValue" new  Class[] {  int . class  });  
  16.         System.out.println("setValue index is : "  + setValue.getIndex());  
  17.   
  18.         FastMethod getValue = clazz.getMethod("getValue" new  Class[] {});  
  19.         System.out.println("getValue index is : "  + getValue.getIndex());  
  20.   
  21.         FastMethod setOther = clazz.getMethod("setOther" new  Class[] {  int . class  });  
  22.         System.out.println("setOther index is : "  + setOther.getIndex());  
  23.   
  24.         FastMethod getOther = clazz.getMethod("getOther" new  Class[] {});  
  25.         System.out.println("getOther index is : "  + getOther.getIndex());  
  26.         // 其他   
  27.         System.out.println("getDeclaredMethods : "  + clazz.getJavaClass().getDeclaredMethods().length);  
  28.         System.out.println("getConstructors : "  + clazz.getJavaClass().getConstructors().length);  
  29.         System.out.println("getFields : "  + clazz.getJavaClass().getFields().length);  
  30.         System.out.println("getMaxIndex : "  + clazz.getMaxIndex());  
  31.     }  
  32. }  
  33.   
  34. class  FastSource {  
  35.     private   int  value;  
  36.     private   int  other;  
  37.   
  38. }  

 

proxy (spring aop相关)

总体类结构图:

Callback & CallbackGenerator

  1. MethodInterceptor
    • 类似于spring aop的around Advise的功能,大家都知道,不多做介绍。唯一需要注意的就是proxy.invokeSuper和proxy.invoke的区别。invokeSuper是退出当前interceptor的处理,进入下一个callback处理,invoke则会继续回调该方法,如果传递给invoke的obj参数出错容易造成递归调用
  2. Dispatcher, ProxyRefDispatcher
    • 类似于delegate的模式,直接将请求分发给具体的Dispatcher调用,是否有着接口+实现分离的味道,将接口的方法调用通过Dispatcher转到实现target上。ProxyRefDispatcher与Dispatcher想比,loadObject()多了个当前代理对象的引用。
    • 反编译的部分代码代码     收藏代码
      1. //反编译的部分代码  
      2. public final int cal(int i, int j)  
      3. {  
      4.         CGLIB$CALLBACK_1;  
      5.         if(CGLIB$CALLBACK_1 != null) goto _L2; else goto _L1  
      6. _L1:  
      7.         JVM INSTR pop ;  
      8.         CGLIB$BIND_CALLBACKS(this);  
      9.         CGLIB$CALLBACK_1;  
      10. _L2:  
      11.         loadObject(); //每次都进行调用  
      12.         (DefaultCalcService);  
      13.         i;  
      14.         j;  
      15.         cal(); //调用实现类的方法  
      16.         return;  
      17.     }   
  3. LazyLoader
    • 相比于Dispatcher,lazyLoader在第一次获取了loadObject后,会进行缓存,后续的请求调用都会直接调用该缓存的属性.
    • 反编译部分代码代码     收藏代码
      1. //反编译部分代码  
      2. public final int cal(int i, int j)  
      3. {  
      4.     this;  
      5.     return ((DefaultCalcService)CGLIB$LOAD_PRIVATE_3()).cal(i, j);  
      6. }  
      7.   
      8. private final synchronized Object CGLIB$LOAD_PRIVATE_3()  
      9. {  
      10.         CGLIB$LAZY_LOADER_3; //保存的属性  
      11.         if(CGLIB$LAZY_LOADER_3 != null) goto _L2; else goto _L1  
      12. _L1:  
      13.         JVM INSTR pop ;  
      14.         this;  
      15.         CGLIB$CALLBACK_3;  
      16.         if(CGLIB$CALLBACK_3 != null) goto _L4; else goto _L3  
      17. _L3:  
      18.         JVM INSTR pop ;  
      19.         CGLIB$BIND_CALLBACKS(this);  
      20.         CGLIB$CALLBACK_3;  
      21. _L4:  
      22.         loadObject();  
      23.         JVM INSTR dup_x1 ;  
      24.         CGLIB$LAZY_LOADER_3;  
      25. _L2:  
      26.         return;  
      27.     }  
  4. NoOp
    • 不做任何处理,结合Filter针对不需要做代理方法直接返回,调用其原始方法
  5. FixedValue
    • 强制方法返回固定值,可结合Filter进行控制
  6. InvocationHandler(提供和jdk proxy的功能),不常用

CallbackFilter

主要的作用就是callback调度,主要的一个方法:int accept(Method method); 
返回的int在int值,代表对应method需要插入的callback,会静态生成到class的代码中,这样是cglib proxy区别于jdk proxy的方式,一个是静态的代码调用,一个是动态的reflect。
可以查看: Enhancer类中的emitMethods方法,line:883。在构造class method字节吗之前就已经确定需要运行的callback。

 

Enhancer

Java代码     收藏代码
  1. System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,  "/home/ljh/cglib" );  
  2. LogInteceptor logInteceptor = new  LogInteceptor();  
  3. CalDispatcher calDispatcher = new  CalDispatcher();  
  4. CalcProxyRefDispatcher calcProxyRefDispatcher = new  CalcProxyRefDispatcher();  
  5. LazyLoaderCallback lazyLoaderCallback = new  LazyLoaderCallback();  
  6.   
  7. Enhancer enhancer = new  Enhancer();  
  8. enhancer.setSuperclass(CalcService.class );  //接口类   
  9. enhancer.setCallbacks(new  Callback[] { logInteceptor, calDispatcher, calcProxyRefDispatcher,lazyLoaderCallback, NoOp.INSTANCE });  // callback数组   
  10. enhancer.setCallbackFilter(new  CalcCallbackFilter());  // filter   
  11. CalcService service = (CalcService) enhancer.create();  
  12.   
  13. int  result = service.cal( 1 1 );  

 

Util  (工具类,感觉有点鸡肋)

  • StringSwitcher 提供string和int的map映射查询,给定一个string字符串,返回同个下标数组的int值,感觉很鸡肋,用Map不是可以很快速的实现功能
  • ParallelSorter 看了具体的代码,没啥意思,就是提供了一个二分的快速排序和多路归并排序。没有所谓的并行排序,原本以为会涉及多线程处理,可惜没有

 

transform

     暂时没仔细研究,更多的是对asm的封装,等下次看了asm代码后再回来研究下。


http://chatgpt.dhexx.cn/article/hNrj0K19.shtml

相关文章

CGLib浅析

CGLib浅析 什么是CGLib CGLIB实现动态代理&#xff0c;并不要求被代理类必须实现接口&#xff0c;底层采用asm字节码生成框架生成代理类字节码(该代理类继承了被代理类)。 所以被代理类一定不能定义为final class并且对于final 方法不能被代理。 实现需要 //MethodIntercept…

CGLIB

1、CGLIB 官网&#xff1a;http://cglib.sourceforge.net CGLIB是一个强大的高性能的代码生成包。它被许多AOP的框架&#xff08;例如Spring AOP&#xff09;使用&#xff0c;为他们提供方法的interception&#xff08;拦截&#xff09;。 Hibernate也使用CGLIB来代理单端si…

CGLIB代理到底是个什么东西?这是一篇最全的CGLIB大全

目录 0 概述 0.1 CGLIB包结构 1 使用CGLIB实现动态代理 1.1 CGLIB代理相关的类 1.2 CGLIB动态代理的基本原理 1.3 使用MethodInterceptor接口实现方法回调 1.3.1 实现MethodInterceptor接口 1.4 使用CGLIB代理最核心类Enhancer生成代理对象 1.5 使用CGLIB继进行动态代理…

什么是CGLIB,CGLIB使用简介

什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c;同样使用CGLIB来代理单端&#xff08;多对一和一对一&#xff09;…

cglib动态代理 | 如何生成代理类、代理类内容解析

文章目录 简介一、cglib动态代理有什么特点CgLib动态代理&#xff1a;优点&#xff1a;缺点&#xff1a; 二、Cglib如何生成代理类生成代理类的具体代码&#xff1a;生成代理对象的具体代码&#xff1a; 三、代理类内容解析持久化代理类&#xff1a;代理类内容&#xff1a; Cgl…

CGLib是什么

什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c;同样使用CGLIB来代理单端&#xff08;多对一和一对一&#xff09;…

什么是CGLIB,CGLIB使用简介,cglib

什么是CGLIB&#xff0c;CGLIB使用简介 2018年08月20日 10:41:31 axiaositong 阅读数&#xff1a;348 什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为…

(转帖)Cglib和jdk动态代理的区别及运行性能比较

动态代理解决了方法之间的紧耦合&#xff0c;IOC解决了类与类之间的紧耦合&#xff01; Cglib和jdk动态代理的区别&#xff1f; 1、Jdk动态代理&#xff1a;利用拦截器&#xff08;必须实现InvocationHandler&#xff09;加上反射机制生成一个代理接口的匿名类&#xff0c;在…

CGLib动态代理原理

CGLib动态代理原理 CGLib动态代理是代理类去继承目标类&#xff0c;然后重写其中目标类的方法啊&#xff0c;这样也可以保证代理类拥有目标类的同名方法&#xff1b; 看一下CGLib的基本结构&#xff0c;下图所示&#xff0c;代理类去继承目标类&#xff0c;每次调用代理类的方…

CGLib介绍

1. CGLIB介绍 CGLIB(Code Generation Library)是一个开源项目&#xff01;是一个强大的&#xff0c;高性能&#xff0c;高质量的Code生成类库&#xff0c; 它可以在运行期扩展Java类与实现Java接口。CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用&#…

cglib的简单使用

一、前言 最近在看Spring的源码&#xff0c;其中有牵扯到cglib的相关内容&#xff0c;遂简单记录下cglib是如何使用的 二、原理&#xff08;节选自网络&#xff09; CGLIB原理&#xff1a;动态生成一个要代理类的子类&#xff0c;子类重写要代理的类的所有不是final的方法。…

cglib动态代理

前面介绍了代理模式和JAVA动态代理&#xff0c;这片文章主要解析cglib动态代理实现。 基本介绍 CGLIB&#xff08;Code Generation Library&#xff09;&#xff0c;是一个强大的&#xff0c;高性能&#xff0c;高质量的 Code 生成类库&#xff0c;它可以在运行期扩展 Java 类…

动态代理之 cglib 实现

&#xff08;尊重劳动成果&#xff0c;转载请注明出处&#xff1a;https://blog.csdn.net/qq_25827845/article/details/87513102冷血之心的博客&#xff09; 目录 前言&#xff1a; 正文&#xff1a; AOP&#xff08;面向切面编程&#xff09; JDK动态代理 cglib实现动态…

CGLIB介绍与原理

一、什么是 CGLIB? CGLIB是一个功能强大&#xff0c;高性能的代码生成包。它为没有实现接口的类提供代理&#xff0c;为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理&#xff0c;但当要代理的类没有实现接口或者为了更好的性能&#xff0c;CGLIB是一个…

CGLIB(Code Generation Library)详解

什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c;同样使用CGLIB来代理单端&#xff08;多对一和一对一&#xff09;…

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

1. CGLIB 动态代理介绍 什么是 CGLIB&#xff1f; CGLIB是一个功能强大&#xff0c;高性能的代码生成包。它为没有实现接口的类提供代理&#xff0c;为JDK的动态代理提供了很好的补充。 通常可以使用Java的动态代理创建代理&#xff0c;但当要代理的类没有实现接口或者为了更…

CGLIB详解(最详细)

转载地址:https://blog.csdn.net/danchu/article/details/70238002 什么是CGLIB CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架&#xff08;Spring、dynaop&#xff09;中&#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架&#xff0c…

GPG error解决方案

问题: sudo apt-get update时报错GPG error 解决方案: // F42ED6FBAB17C654是根据你报错那一行确定的 sudo gpg --keyserver keyserver.ubuntu.com --recv F42ED6FBAB17C654 sudo gpg --export --armor F42ED6FBAB17C654 | sudo apt-key add -然后: sudo apt-get update

GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

阿里云CentOS 7.9 64位 搭建网站踩坑实录 问题1.GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql Failing package is: mysql-community-libs-compat-5.7.37-1.el7.x86_64 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql …

gpg文件加密解密

使用Ubuntu对文件进行gpg格式的加密和解密 安装 下载源码安装  ./configure   make   make install 命令安装 Debian环境 sudo apt-get install gnupg Fedora 环境 yum install gnupg 加密 gpg -c abc.txt 会让输入一个加密的密码&#xff0c;需要自己输入 解密 gpg -o …