建设境外网站,推广链接点击器,即时设计网页,四川建设行政主管部门官方网站CGLIB CGLIB简介#xff1a;
什么是CGLIB
CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架#xff08;Spring、dynaop#xff09;中#xff0c;用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架#xff0c;同样使用CGLIB来代理单端#xff…CGLIB CGLIB简介
什么是CGLIB
CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架Spring、dynaop中用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架同样使用CGLIB来代理单端多对一和一对一关联延迟提取集合使用的另一种机制。CGLIB作为一个开源项目其代码托管在github地址为GitHub - cglib/cglib: cglib - Byte Code Generation Library is high level API to generate and transform Java byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access.
为什么使用CGLIB
CGLIB代理主要通过对字节码的操作为对象引入间接级别以控制对象的访问。我们知道Java中有一个动态代理也是做这个事情的那我们为什么不直接使用Java动态代理而要使用CGLIB呢答案是CGLIB相比于JDK动态代理更加强大JDK动态代理虽然简单易用但是其有一个致命缺陷是只能对接口进行代理。如果要代理的类为一个普通类、没有接口那么Java动态代理就没法使用了。关于Java动态代理可以参者这里Java动态代理分析
CGLIB组成结构 CGLIB底层使用了ASM一个短小精悍的字节码操作框架来操作字节码生成新的类。除了CGLIB库外脚本语言如Groovy何BeanShell也使用ASM生成字节码。ASM使用类似SAX的解析器来实现高性能。我们不鼓励直接使用ASM因为它需要对Java字节码的格式足够的了解 例子
说了这么多可能大家还是不知道CGLIB是干什么用的。下面我们将使用一个简单的例子来演示如何使用CGLIB对一个方法进行拦截。 首先我们需要在工程的POM文件中引入cglib的dependency这里我们使用的是2.2.2版本
dependencygroupIdcglib/groupIdartifactIdcglib/artifactIdversion2.2.2/version
/dependency
依赖包下载后我们就可以干活了按照国际惯例写个hello world
public class SampleClass {public void test(){System.out.println(hello world);}public static void main(String[] args) {Enhancer enhancer new Enhancer();enhancer.setSuperclass(SampleClass.class);enhancer.setCallback(new MethodInterceptor() {Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println(before method run...);Object result proxy.invokeSuper(obj, args);System.out.println(after method run...);return result;}});SampleClass sample (SampleClass) enhancer.create();sample.test();}
}
在mian函数中我们通过一个Enhancer和一个MethodInterceptor来实现对方法的拦截运行程序后输出为
before method run...
hello world
after method run...
在上面的程序中我们引入了Enhancer和MethodInterceptor就目前而言一个使用CGLIB的小demo就完成了。
通过callback在函数前后增加了代码功能。
通过enhancer.setSuperclass(SampleClass.class) 设置代理的类。 superclass记录需要代理的类
然后通过create()创建代理对象 通过反射创建实例对象 通过setCallBack设置回调函数 如何获取的代理对象的方法 通过superClass获取methods方法保存。 如何将代理对象的方法设置到 CGLIB对象上 TODO
如何调用方法时调用callback函数TODO 注意
由于CGLIB的大部分类是直接对Java字节码进行操作这样生成的类会在Java的永久堆中。如果动态代理操作过多容易造成永久堆满触发OutOfMemory异常。
CGLIB和Java动态代理的区别
Java动态代理只能够对接口进行代理不能对普通的类进行代理因为所有生成的代理类的父类为ProxyJava类继承机制不允许多重继承CGLIB能够代理普通类Java动态代理使用Java原生的反射API进行操作在生成类上比较高效CGLIB使用ASM框架直接对字节码进行操作在类的执行过程中比较高效
知识来源
【23版面试突击】描述动态代理的几种实现方式分别说出相应的优缺点_哔哩哔哩_bilibili
CGLIB详解(最详细)__抱歉打扰了的博客-CSDN博客CGLIB(Code Generation Library) 介绍与原理 | 菜鸟教程