【spring篇】CJLIB 动态代理

目录

什么是cjlib动态代理?

CGLIB的实现技术

 底层实现原理

CGLIB动态代理的实现原理:

 使用cjlib动态代理技术为什么要使用Enhancer对象

Intercept方法


与JDK动态代理对比着看,使更容易理解;

 

什么是cjlib动态代理?

CGLIB(Code Generation Library)是一种用于生成字节码并创建动态代理类的动态代理库。与JDK动态代理不同,CGLIB可以代理类而不仅仅是接口,因此更适用于那些没有实现接口的类。

CGLIB通过在运行时生成目标类的子类,并在子类中重写或增加方法来实现动态代理。这种方式与JDK动态代理使用接口的方式不同。在使用CGLIB动态代理时,生成的代理类是目标类的子类,而不是实现了某个接口的类。

总的来说,CGLIB是一种强大的动态代理技术,特别适用于那些无法或方便使用接口的情况。在面向切面编程(AOP)等场景中,CGLIB通常被用于生成代理类,以实现横切关注点的功能。

CGLIB的实现技术

在CGLIB中有两个重要的技术,Enhancer 和 MethodInterceptor ,它们在CGLIB动态代理中分别起到不同的作用:

  1. Enhancer:

    • 作用: 用于创建动态代理类。它负责配置和生成代理类的过程。
    • 功能:
      • 设置代理类的父类。
      • 指定回调对象,即处理方法调用的对象。
      • 设置过滤器,用于控制哪些方法需要被代理。
      • 生成代理类的实例。
  2. MethodInterceptor:

    • 作用: MethodInterceptor 接口定义了代理对象的拦截逻辑,用于在调用代理对象的方法时添加横切逻辑。
    • 功能:
      • 在 intercept 方法中实现代理逻辑,包括前置处理、调用目标方法、后置处理等。
      • 提供了 objmethodargsproxy 参数,用于获取被代理对象、被调用方法、方法参数和代理对象。

通过结合使用 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动态代理的实现原理:

  1. 字节码生成: CGLIB使用ASM(Java字节码操作和分析框架)等工具,在运行时生成目标类的子类。这个子类继承自目标类,拥有目标类的所有非私有方法。

  2. 方法拦截: CGLIB生成的子类中,被代理类的方法会被重写。在重写的方法中,会插入代理逻辑,即通知(advice)。这样,在调用被代理类的方法时,实际上调用的是CGLIB生成的子类的方法,从而执行了代理逻辑。

  3. 目标对象引用: CGLIB生成的子类中通常包含一个指向目标对象的引用,以便在代理逻辑中能够调用目标对象的方法。

  4. 动态类加载: CGLIB生成的子类的字节码会在运行时通过类加载器动态加载到内存中,成为新的类。这个过程通常发生在目标类首次被代理时。

  5. 织入(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();
    }

 

 使用cjlib动态代理技术为什么要使用Enhancer对象

在CGLIB中,Enhancer 是一个用于创建动态代理类的关键类。使用 Enhancer 对象是为了配置和生成代理类的过程。以下是为什么要使用 Enhancer 对象的一些原因:

  1. 配置代理类: Enhancer 提供了一系列方法,可以用来配置代理类的行为,例如设置父类、指定回调(Callback)、设置过滤器(Filter)等。通过这些配置,可以定制生成的代理类的特性。

  2. 设置父类: 使用 Enhancer 可以指定生成的代理类的父类,这是CGLIB与JDK动态代理不同的地方。被代理类的方法会被继承到生成的代理类中,并可以在代理类中重写或增加方法

  3. 设置回调: Enhancer 允许设置回调对象,即用于处理方法调用的对象。回调通常是实现了 MethodInterceptor 接口的对象,它的 intercept 方法中包含了代理逻辑。

  4. 设置过滤器: 可以通过 Enhancer 设置过滤器来控制哪些方法需要被代理。过滤器是一个实现了 CallbackFilter 接口的对象,根据方法的索引返回相应的回调对象。

  5. 生成代理类实例: 通过 Enhancer 的 create 方法可以生成代理类的实例。这个实例可以用来调用被代理类的方法,并在方法调用前后执行代理逻辑。

Enhancer 被用来设置父类、回调对象,并最终生成代理类的实例。通过 MethodInterceptor 的实现,可以在代理逻辑中添加横切关注点。


Intercept方法

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 方法实现了一个简单的前置处理和后置处理逻辑。你可以根据实际需求编写更复杂的代理逻辑。

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值