CGLIB中的常用API

CGLIB

CGLIB,即Code Generation Library,是一个开源项目。Github地址:https://github.com/cglib/cglib

CGLIB的github简介:CGLIB - 字节码生成库,是用于生成和转换Java字节码的高级API。它被AOP、测试、数据访问框架用于生成动态代理对象和拦截字段访问。

CGLIB提供两种类型的JAR包:

  • cglib-nodep-x.x.x.jar:使用nodep包不需要关联ASM的jar包,jar包内部包含ASM的类库。
  • cglib-x.x.x.jar:使用此jar包需要另外提供ASM的jar包,否则运行时报错,建议选用不包含ASM类库的jar包,可以方便控制ASM的。

本文中使用的CGLIB依赖为:

<dependency>
  <groupId>cglib</groupId>
	<artifactId>cglib-nodep</artifactId>
	<version>3.2.10</version>
</dependency>

<dependency>
  <groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.16.22</version>
</dependency>

CGLIB基本原理

  • 基本原理:动态生成一个要代理类的子类(被代理的类作为继承的父类),子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用Java反射的JDK动态代理要快,因为它采用了整形变量建立了方法索引。
  • 底层实现:使用字节码处理框架ASM,用于转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求必须对JVM内部结构包括class文件的格式和JVM指令集都很熟悉,否则一旦出现错误将会是JVM崩溃级别的异常

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常用API

下面介绍一下CGLIB中常用的几个API,先建立一个模特接口类和普通模特类:

public class SampleClass {
   

	public String sayHello(String name) {
   
		return String.format("%s say hello!", name);
	}
}

public interface SampleInterface {
   

	String sayHello(String name);
}

Enhancer

Enhancer,即(字节码)增强器。它是CGLIB库中最常用的一个类,功能与JDK动态代理中引入的Proxy类差不多,但是Enhancer既能够代理普通的Java类,也能够代理接口。

Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。

Enhancer不能够拦截final方法,例如Object.getClass()方法,这是由于final关键字的语义决定的。基于同样的道理,Enhancer也不能对fianl类进行代理操作。这也是Hibernate为什么不能持久化final关键字修饰的类的原因。

public class EnhancerClassDemo {
   

	public static void main(String[] args) throws Exception {
   
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(SampleClass.class);
    //使用FixedValue,拦截返回值,每次返回固定值"Doge say hello!"
		enhancer.setCallback((FixedValue) () -> "Doge say hello!");
    
		SampleClass sampleClass = (SampleClass) enhancer.create();
		System.out.println(sampleClass.sayHello("throwable-10086"));
		System.out.println(sampleClass.sayHello("throwable-doge"));
		System.out.println(sampleClass.toString());
		System.out.println(sampleClass.getClass());
		System.out.println(sampleClass.hashCode());
	}
}

输出结果:


                
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值