通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

java 中的 Cglib 代理如何使用

java 中的 Cglib 代理如何使用

CGLIB 库是一个强大的、高性能、高品质的Code生成库,用于在运行时扩展Java类与实现Java接口。CGLib代理的主要用途是针对类创建一个子类、在运行时扩充对象行为;而JDK动态代理则是针对接口实现代理。使用CGLib时,不必要求目标对象必须实现接口。CGLib由于是在运行时生成类的子类来实现,因此被称为子类代理。它的使用涉及到创建增强器、设置回调处理器以及生成代理等步骤。

一、CGLIB代理概述

CGLIB代理的使用广泛应用在诸如Spring框架中用于实现AOP(面向切面编程)功能。它通过底层的字节码技术,为一个类创建一个子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,并判断是否进行增强。

二、实现CGLIB代理的步骤

创建一个类需要被代理的类,称它为BaseClass。

public class BaseClass {

public void doSomething(){

System.out.println("Doing something");

}

}

定义一个MethodInterceptor这是CGLib在调用代理对象中拦截到被代理方法时候,所要执行的方法拦截器。

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class BaseClassInterceptor implements MethodInterceptor {

@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

System.out.println("Before method execute");

Object result = proxy.invokeSuper(obj, args);

System.out.println("After method execute");

return result;

}

}

生成CGLIB代理对象通过Enhancer类可以创建CGLIB代理对象,增强器enhancer.setSuperclass用于设置生成类的父类,enhancer.setCallback用于设置回调,调用enhancer.create生成代理对象。

import net.sf.cglib.proxy.Enhancer;

public class CglibProxyCreator {

public static BaseClass createProxy() {

Enhancer enhancer = new Enhancer();

enhancer.setSuperclass(BaseClass.class);

enhancer.setCallback(new BaseClassInterceptor());

return (BaseClass) enhancer.create();

}

}

三、CGLIB代理的高级特性

CGLIB不仅仅能够实现简单的代理,在实践中,通常会结合各种高级特性来完成复杂的需求。

方法过滤CGLIB提供了CallbackFilter接口,可以用于在生成代理对象时,对不同的方法应用不同的回调逻辑。

import net.sf.cglib.proxy.CallbackFilter;

import java.lang.reflect.Method;

public class BaseClassCallbackFilter implements CallbackFilter {

@Override

public int accept(Method method) {

if ("doSomething".equals(method.getName())) {

return 0; // 使用索引为0的回调

}

return 1; // 使用索引为1的回调

}

}

通过这个CallbackFilter,我们可以控制不同方法执行不同的回调逻辑。

多个回调CGLIB支持使用多个回调并结合CallbackFilter使用。

enhancer.setCallbacks(new Callback[]{new BaseClassInterceptor(), NoOp.INSTANCE});

enhancer.setCallbackFilter(new BaseClassCallbackFilter());

在上述代码中,NoOp.INSTANCE是CGLIB提供的一个Callback,它会直接放行该方法的调用,不会做任何处理。

有状态的和无状态的回调有状态的回调Callback会在多次调用中保留状态信息,而无状态的则不会。MethodInterceptor是有状态的,每次代理对象的方法被调用都会进入相同的MethodInterceptor实现。

四、CGLIB代理的性能

相对于JDK动态代理,CGLIB通常会有更好的执行性能,原因在于CGLIB生成的是真正的类而非接口的实现。在Java的动态代理上,每次调用代理对象的方法时,都会转发到InvocationHandler的invoke方法,而CGLIB则通过直接扩展类并在子类中添加了方法拦截逻辑来实现。然而,由于需要动态生成字节码,在创建代理对象的时候CGLIB的开销会比较大。

五、CGLIB代理的局限性

无法代理final方法由于CGLIB是通过继承的方式生成代理对象,Java语言规范禁止父类的final方法被子类覆盖。因此在CGLIB代理中,被final修饰的方法无法进行拦截和增强。

针对构造器的限制CGLIB在创建子类时,会自动调用超类(即被代理类)的无参数构造器。如果原始类没有提供无参数的构造器,就需要在子类中手工编码调用其他的构造器。如果原始类的构造器具有副作用或者执行成本较高,这将会是一个问题。

综上所述,CGLIB提供了一种强大的方式来创建运行时代理,特别适用于无法修改代码或者无法实现接口的情况下。与JDK动态代理相比,CGLIB在运行时性能上更有优势,但其初始化成本更高,且不支持final方法以及具有某些构造器限制。在实际使用中,选择CGLIB还是JDK动态代理,要根据具体需求进行考量。

相关问答FAQs:

Cglib代理是什么?它与Java动态代理的区别是什么?

Cglib代理是一种基于字节码的代理机制,它通过创建目标类的子类来实现代理。与Java动态代理不同,它可以代理非接口类型的类。

如何使用Cglib代理?

要使用Cglib代理,首先需要引入Cglib库,然后创建一个Enhancer对象。通过调用Enhancer对象的setSuperclass()方法设置目标类,调用setCallback()方法设置回调处理器,最后调用create()方法创建代理对象。

Cglib代理的优缺点是什么?

Cglib代理的优点是它可以代理非接口类型的类,相比于Java动态代理更加灵活。它还能够实现对目标类方法细粒度的代理控制。

然而,Cglib代理的缺点是它在创建代理对象时的性能相对较低,因为它涉及到对字节码的操作。此外,Cglib代理不能代理被final关键字修饰的方法。

请注意,在使用Cglib代理时,目标类和被代理的方法不能是final修饰的。

相关文章