目录
什么是cjlib动态代理?
CGLIB的实现技术
底层实现原理
CGLIB动态代理的实现原理:
使用cjlib动态代理技术为什么要使用Enhancer对象
Intercept方法
与JDK动态代理对比着看,使更容易理解;
CGLIB(Code Generation Library)是一种用于生成字节码并创建动态代理类的动态代理库。与JDK动态代理不同,CGLIB可以代理类而不仅仅是接口,因此更适用于那些没有实现接口的类。
CGLIB通过在运行时生成目标类的子类,并在子类中重写或增加方法来实现动态代理。这种方式与JDK动态代理使用接口的方式不同。在使用CGLIB动态代理时,生成的代理类是目标类的子类,而不是实现了某个接口的类。
总的来说,CGLIB是一种强大的动态代理技术,特别适用于那些无法或不方便使用接口的情况。在面向切面编程(AOP)等场景中,CGLIB通常被用于生成代理类,以实现横切关注点的功能。
在CGLIB中有两个重要的技术,Enhancer
和 MethodInterceptor
,它们在CGLIB动态代理中分别起到不同的作用:
Enhancer:
MethodInterceptor:
MethodInterceptor
接口定义了代理对象的拦截逻辑,用于在调用代理对象的方法时添加横切逻辑。intercept
方法中实现代理逻辑,包括前置处理、调用目标方法、后置处理等。obj
、method
、args
、proxy
参数,用于获取被代理对象、被调用方法、方法参数和代理对象。通过结合使用 Enhancer
和 MethodInterceptor
,可以实现对目标对象的动态代理。Enhancer
用于配置和生成代理类,而 MethodInterceptor
用于定义代理逻辑。以下是一个简单的示例:
public class MyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 前置处理逻辑
System.out.println("Before invoking method: " + method.getName());
// 调用目标方法
Object result = proxy.invokeSuper(obj, args);
// 后置处理逻辑
System.out.println("After invoking method: " + method.getName());
return result;
}
public static void main(String[] args) {
// 使用Enhancer创建代理类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback(new MyInterceptor());
// 生成代理类的实例
MyClass proxyInstance = (MyClass) enhancer.create();
// 调用代理对象的方法
proxyInstance.someMethod();
}
}
在这个例子中,Enhancer
设置了被代理类的父类和回调对象,而 MyInterceptor
实现了具体的代理逻辑。最终,通过 Enhancer
创建的代理类实例可以在调用方法时触发 MyInterceptor
中定义的逻辑。
CGLIB(Code Generation Library)是一个用于生成字节码并创建动态代理类的开源库。它的主要特点是能够代理没有实现接口的类,与JDK动态代理不同,它是通过生成目标类的子类来实现代理的。
字节码生成: CGLIB使用ASM(Java字节码操作和分析框架)等工具,在运行时生成目标类的子类。这个子类继承自目标类,拥有目标类的所有非私有方法。
方法拦截: CGLIB生成的子类中,被代理类的方法会被重写。在重写的方法中,会插入代理逻辑,即通知(advice)。这样,在调用被代理类的方法时,实际上调用的是CGLIB生成的子类的方法,从而执行了代理逻辑。
目标对象引用: CGLIB生成的子类中通常包含一个指向目标对象的引用,以便在代理逻辑中能够调用目标对象的方法。
动态类加载: CGLIB生成的子类的字节码会在运行时通过类加载器动态加载到内存中,成为新的类。这个过程通常发生在目标类首次被代理时。
织入(Weaving): 生成的子类与目标对象关联的过程被称为织入。织入可以在编译时、类加载时或运行时进行。CGLIB通常采用运行时织入的方式,即在目标类被加载到内存后,通过生成的子类与目标对象关联。
总的来说,CGLIB通过生成目标类的子类,并在子类中插入代理逻辑,实现了对目标类的动态代理。这使得在运行时能够在目标方法的执行前后插入横切逻辑,从而实现面向切面编程的功能。
public static void main(String[] args) {
// 使用Enhancer创建代理类
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback(new MyInterceptor());
// 生成代理类的实例
MyClass proxyInstance = (MyClass) enhancer.create();
// 调用代理对象的方法
proxyInstance.someMethod();
}
在CGLIB中,Enhancer
是一个用于创建动态代理类的关键类。使用 Enhancer
对象是为了配置和生成代理类的过程。以下是为什么要使用 Enhancer
对象的一些原因:
配置代理类: Enhancer
提供了一系列方法,可以用来配置代理类的行为,例如设置父类、指定回调(Callback)、设置过滤器(Filter)等。通过这些配置,可以定制生成的代理类的特性。
设置父类: 使用 Enhancer
可以指定生成的代理类的父类,这是CGLIB与JDK动态代理不同的地方。被代理类的方法会被继承到生成的代理类中,并可以在代理类中重写或增加方法。
设置回调: Enhancer
允许设置回调对象,即用于处理方法调用的对象。回调通常是实现了 MethodInterceptor
接口的对象,它的 intercept
方法中包含了代理逻辑。
设置过滤器: 可以通过 Enhancer
设置过滤器来控制哪些方法需要被代理。过滤器是一个实现了 CallbackFilter
接口的对象,根据方法的索引返回相应的回调对象。
生成代理类实例: 通过 Enhancer
的 create
方法可以生成代理类的实例。这个实例可以用来调用被代理类的方法,并在方法调用前后执行代理逻辑。
Enhancer
被用来设置父类、回调对象,并最终生成代理类的实例。通过MethodInterceptor
的实现,可以在代理逻辑中添加横切关注点。
intercept
方法是net.sf.cglib.proxy.MethodInterceptor
接口中定义的方法,用于定义代理对象的具体逻辑。该方法在调用代理对象的方法时被触发,允许在目标方法执行前后添加横切逻辑。
Object intercept(Object obj, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;
参数说明:
obj: 被代理对象的实例,即生成的代理类的实例。
method: 被代理方法的反射对象,包含了被调用的方法的信息。
args: 被调用方法的参数数组。
proxy: MethodProxy
对象,用于调用父类的方法或者调用其他代理方法。
返回值:代理方法的返回值,类型为 Object
。
在 intercept
方法中,你可以编写代理逻辑,实现在目标方法执行前后进行一些操作。通常,你会在方法的开始部分添加一些前置处理逻辑,然后通过 proxy.invokeSuper(obj, args)
调用目标方法,最后在方法的结束部分添加一些后置处理逻辑。
以下是一个简单的例子:
public class MyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 前置处理逻辑
System.out.println("Before invoking method: " + method.getName());
// 调用目标方法
Object result = proxy.invokeSuper(obj, args);
// 后置处理逻辑
System.out.println("After invoking method: " + method.getName());
return result;
}
在这个例子中,intercept
方法实现了一个简单的前置处理和后置处理逻辑。你可以根据实际需求编写更复杂的代理逻辑。