Spring中JDK动态代理和CGLIB动态代理的性能比较

本文通过实验对比了Cglib与JDK动态代理在不同JDK版本下的性能表现,结果显示Cglib在JDK6下稍优于JDK动态代理,但在JDK7及以后版本中,JDK动态代理的性能显著提高并超越Cglib。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 http://www.cnblogs.com/haiq/p/4304615.html

都说 Cglib 创建的动态代理的运行性能比 JDK 动态代理能高出大概 10 倍,今日抱着怀疑精神验证了一下,发现情况有所不同,遂贴出实验结果,以供参考和讨论。

代码很简单,首先,定义一个 Test 接口,和一个实现 TestImpl 。Test 接口仅定义一个方法 test,对传入的 int 参数加 1 后返回。代码如下:

复制代码
package my.test;

public interface Test {
    
    public int test(int i);
    
}
复制代码

 

复制代码
package my.test;

public class TestImpl implements Test{
    public int test(int i) {
        return i+1;
    }
}
复制代码

 

 

然后,定义了三种代理的实现:装饰者模式实现的代理(decorator),JDK 动态代理(dynamic proxy) 和 Cglib 动态代理 (cglib proxy)。代码如下:

复制代码
package my.test;

public class DecoratorTest implements Test{
    private Test target;
    
    public DecoratorTest(Test target) {
        this.target = target;
    }

    public int test(int i) {
        return target.test(i);
    }
}
复制代码

 

复制代码
package my.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyTest implements InvocationHandler {
    private Test target;

    private DynamicProxyTest(Test target) {
        this.target = target;
    }

    public static Test newProxyInstance(Test target) {
        return (Test) Proxy
                .newProxyInstance(DynamicProxyTest.class.getClassLoader(),
                        new Class<?>[] { Test.class },
                        new DynamicProxyTest(target));

    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        return method.invoke(target, args);
    }
}
复制代码
复制代码
package my.test;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxyTest implements MethodInterceptor {
    
    private CglibProxyTest() {
    }
    
    public static <T extends Test> Test newProxyInstance(Class<T> targetInstanceClazz){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetInstanceClazz);
        enhancer.setCallback(new CglibProxyTest());
        return (Test) enhancer.create();
    }

    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        return proxy.invokeSuper(obj, args);
    }

}
复制代码

 

 

以 TestImpl 的调用耗时作为基准,对比通过其它三种代理进行调用的耗时。测试代码如下:

复制代码
package my.test;

import java.util.LinkedHashMap;
import java.util.Map;

public class ProxyPerfTester {

    public static void main(String[] args) {
        //创建测试对象;
        Test nativeTest = new TestImpl();
        Test decorator = new DecoratorTest(nativeTest);
        Test dynamicProxy = DynamicProxyTest.newProxyInstance(nativeTest);
        Test cglibProxy = CglibProxyTest.newProxyInstance(TestImpl.class);

        //预热一下;
        int preRunCount = 10000;
        runWithoutMonitor(nativeTest, preRunCount);
        runWithoutMonitor(decorator, preRunCount);
        runWithoutMonitor(cglibProxy, preRunCount);
        runWithoutMonitor(dynamicProxy, preRunCount);
        
        //执行测试;
        Map<String, Test> tests = new LinkedHashMap<String, Test>();
        tests.put("Native   ", nativeTest);
        tests.put("Decorator", decorator);
        tests.put("Dynamic  ", dynamicProxy);
        tests.put("Cglib    ", cglibProxy);
        int repeatCount = 3;
        int runCount = 1000000;
        runTest(repeatCount, runCount, tests);
        runCount = 50000000;
        runTest(repeatCount, runCount, tests);
    }
    
    private static void runTest(int repeatCount, int runCount, Map<String, Test> tests){
        System.out.println(String.format("\n==================== run test : [repeatCount=%s] [runCount=%s] [java.version=%s] ====================", repeatCount, runCount, System.getProperty("java.version")));
        for (int i = 0; i < repeatCount; i++) {
            System.out.println(String.format("\n--------- test : [%s] ---------", (i+1)));
            for (String key : tests.keySet()) {
                runWithMonitor(tests.get(key), runCount, key);
            }
        }
    }
    
    private static void runWithoutMonitor(Test test, int runCount) {
        for (int i = 0; i < runCount; i++) {
            test.test(i);
        }
    }
    
    private static void runWithMonitor(Test test, int runCount, String tag) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < runCount; i++) {
            test.test(i);
        }
        long end = System.currentTimeMillis();
        System.out.println("["+tag + "] Elapsed Time:" + (end-start) + "ms");
    }
}
复制代码

 

 

测试用例分别在 jdk6、 jdk7、jdk8 下进行了测试,每次测试分别以 1,000,000 和 50,000,000 循环次数调用 test 方法,并重复3次。

  • jdk6 下的测试结果如下:
复制代码
==================== run test : [repeatCount=3] [runCount=1000000] [java.version=1.6.0_45] ====================

--------- test : [1] ---------
[Native   ] Elapsed Time:2ms
[Decorator] Elapsed Time:12ms
[Dynamic  ] Elapsed Time:31ms
[Cglib    ] Elapsed Time:31ms

--------- test : [2] ---------
[Native   ] Elapsed Time:7ms
[Decorator] Elapsed Time:7ms
[Dynamic  ] Elapsed Time:31ms
[Cglib    ] Elapsed Time:27ms

--------- test : [3] ---------
[Native   ] Elapsed Time:7ms
[Decorator] Elapsed Time:6ms
[Dynamic  ] Elapsed Time:23ms
[Cglib    ] Elapsed Time:29ms

==================== run test : [repeatCount=3] [runCount=50000000] [java.version=1.6.0_45] ====================

--------- test : [1] ---------
[Native   ] Elapsed Time:212ms
[Decorator] Elapsed Time:226ms
[Dynamic  ] Elapsed Time:1054ms
[Cglib    ] Elapsed Time:830ms

--------- test : [2] ---------
[Native   ] Elapsed Time:184ms
[Decorator] Elapsed Time:222ms
[Dynamic  ] Elapsed Time:1020ms
[Cglib    ] Elapsed Time:826ms

--------- test : [3] ---------
[Native   ] Elapsed Time:184ms
[Decorator] Elapsed Time:208ms
[Dynamic  ] Elapsed Time:979ms
[Cglib    ] Elapsed Time:832ms
复制代码

 

  测试结果表明:jdk6 下,在运行次数较少的情况下,jdk动态代理与 cglib 差距不明显,甚至更快一些;而当调用次数增加之后, cglib 表现稍微更快一些,然而仅仅是“稍微”好一些,远没达到 10 倍差距。

  • jdk7 下的测试结果如下:
复制代码
==================== run test : [repeatCount=3] [runCount=1000000] [java.version=1.7.0_60] ====================

--------- test : [1] ---------
[Native   ] Elapsed Time:2ms
[Decorator] Elapsed Time:12ms
[Dynamic  ] Elapsed Time:19ms
[Cglib    ] Elapsed Time:26ms

--------- test : [2] ---------
[Native   ] Elapsed Time:3ms
[Decorator] Elapsed Time:5ms
[Dynamic  ] Elapsed Time:17ms
[Cglib    ] Elapsed Time:20ms

--------- test : [3] ---------
[Native   ] Elapsed Time:4ms
[Decorator] Elapsed Time:4ms
[Dynamic  ] Elapsed Time:13ms
[Cglib    ] Elapsed Time:27ms

==================== run test : [repeatCount=3] [runCount=50000000] [java.version=1.7.0_60] ====================

--------- test : [1] ---------
[Native   ] Elapsed Time:208ms
[Decorator] Elapsed Time:210ms
[Dynamic  ] Elapsed Time:551ms
[Cglib    ] Elapsed Time:923ms

--------- test : [2] ---------
[Native   ] Elapsed Time:238ms
[Decorator] Elapsed Time:210ms
[Dynamic  ] Elapsed Time:483ms
[Cglib    ] Elapsed Time:872ms

--------- test : [3] ---------
[Native   ] Elapsed Time:217ms
[Decorator] Elapsed Time:208ms
[Dynamic  ] Elapsed Time:494ms
[Cglib    ] Elapsed Time:881ms
复制代码

 

测试结果表明:jdk7 下,情况发生了逆转!在运行次数较少(1,000,000)的情况下,jdk动态代理比 cglib 快了差不多30%;而当调用次数增加之后(50,000,000), 动态代理比 cglib 快了接近1倍。

接下来再看看jdk8下的表现如何。

  • jdk8 下的测试结果如下:
复制代码
==================== run test : [repeatCount=3] [runCount=1000000] [java.version=1.8.0_05] ====================

--------- test : [1] ---------
[Native   ] Elapsed Time:5ms
[Decorator] Elapsed Time:11ms
[Dynamic  ] Elapsed Time:27ms
[Cglib    ] Elapsed Time:52ms

--------- test : [2] ---------
[Native   ] Elapsed Time:4ms
[Decorator] Elapsed Time:6ms
[Dynamic  ] Elapsed Time:11ms
[Cglib    ] Elapsed Time:24ms

--------- test : [3] ---------
[Native   ] Elapsed Time:4ms
[Decorator] Elapsed Time:5ms
[Dynamic  ] Elapsed Time:9ms
[Cglib    ] Elapsed Time:26ms

==================== run test : [repeatCount=3] [runCount=50000000] [java.version=1.8.0_05] ====================

--------- test : [1] ---------
[Native   ] Elapsed Time:194ms
[Decorator] Elapsed Time:211ms
[Dynamic  ] Elapsed Time:538ms
[Cglib    ] Elapsed Time:965ms

--------- test : [2] ---------
[Native   ] Elapsed Time:194ms
[Decorator] Elapsed Time:214ms
[Dynamic  ] Elapsed Time:503ms
[Cglib    ] Elapsed Time:969ms

--------- test : [3] ---------
[Native   ] Elapsed Time:190ms
[Decorator] Elapsed Time:209ms
[Dynamic  ] Elapsed Time:495ms
[Cglib    ] Elapsed Time:939ms
复制代码

 

测试结果表明:jdk8 下,延续了 JDK7 下的惊天大逆转!不过还观察另外有一个细微的变化,从绝对值来看 cglib 在 jdk8 下的表现似乎比 jdk7 还要差一点点,尽管只是一点点,但经过反复多次的执行仍然是这个趋势(注:这个趋势的结论并不严谨,只是捎带一提,如需得出结论还需进行更多样的对比实验)。

 

结论:从 jdk6 到 jdk7、jdk8 ,动态代理的性能得到了显著的提升,而 cglib 的表现并未跟上,甚至可能会略微下降。传言的 cglib 比 jdk动态代理高出 10 倍的情况也许是出现在更低版本的 jdk 上吧。

以上测试用例虽然简单,但揭示了 jdk 版本升级可能会带来一些新技术改变,会使我们以前的经验失效。放在真实业务场景下时,还需要按照实际情况进行测试后才能得出特定于场景的结论。

总之,实践出真知,还要与时俱进地去检视更新一些以往经验。

 

注:上述实验中 cglib 的版本是 3.1 。


================================================================================

http://www.thinksaas.cn/group/topic/130731/

 新项目开始之前领导让研究下公司原有的框架(基于struts1.2.9+spring2.0.6),比较古老了。读service基类时发现竟然将request穿透到了service层(request为BaseService的实例变量),这样service就变成了有状态Bean,使service层变成了非线程安全,导致用Spring容器管理service的时候不得不使用prototype的scope     我们知道,service由于要做事务的包装,需要创建代理对象,spring中使用JDK动态代理或者CGLIB动态代理来创建代理对象,据说JDK动态代理创建对象的时间快于CGLIB,但是性能比CGLIB差(接下来我会测试这个观点),所以我得出以下结论: 1.spring在bean的scope为prototype的情况下,因为是延迟实例化bean,所以最好使用JDK的API创建代理对象; 2.反之对于singleton对象,spring默认是容器启动时就初始化bean,最好使用CGLIB来创建对象 把service配置成singleton我觉得性能方面显然要更好些,如果非要将request穿透到service层,是不是可以考虑用ThreadLocal? 在测试之前,我们先确定spring是以什么方式使用JDK动态代理和CGLIB的,如图: JDK动态代理:CGLIB动态代理:接下来对测试下JDK动态代理和CGLIB动态代理的性能(CGLIB测试代码也和spring一样使用MethodInterceptor) 先贴上测试代码

public interface CountService {
 int count();
}
public class CountServiceImpl implements CountService {
 private int count = 0;

 public int count() {
 return ++count;
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.DecimalFormat;

import net.sf.cglib.core.DefaultGeneratorStrategy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

@SuppressWarnings("unused")
public class DynamicProxyPerformanceTest {

 public static void main(String[] args) throws Exception {
 CountService delegate = new CountServiceImpl();

 long time = System.currentTimeMillis();
 CountService jdkProxy = createJdkDynamicProxy(delegate);
 time = System.currentTimeMillis() - time;
 System.out.println("Create JDK Proxy:"+ time +"ms");

 time = System.currentTimeMillis();
 CountService cglibProxy = createCglibDynamicProxy(delegate);
 time = System.currentTimeMillis() - time;
 System.out.println("Create CGLIB Proxy:"+ time +"ms");

 for (int i = 0; i < 3; i++) {
 test(jdkProxy,"Run JDK Proxy:");
 test(cglibProxy,"Run CGLIB Proxy:");
System.out.println("-------------------");
}
}

 private static void test(CountService service, String label) throws Exception {
 service.count(); // warm up
 int count = 10000000;
 long time = System.currentTimeMillis();
 for (int i = 0; i < count; i++) {
service.count();
}
 time = System.currentTimeMillis() - time;
 System.out.println(label + time +"ms,"+ new DecimalFormat().format(count * 1000 / time) +"t/s");
}

 private static CountService createJdkDynamicProxy(final CountService delegate) {
 CountService jdkProxy = (CountService) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
 new Class[] { CountService.class }, new JdkHandler(delegate));

 // 反汇编字节码用,测试的时候注释掉这段代码,不然影响测试结果
 // 下面一行代码参照java.lang.reflect.Proxy
// byte[] proxyClassFile =
// sun.misc.ProxyGenerator.generateProxyClass(
// jdkProxy.getClass().getName(), jdkProxy.getClass().getInterfaces());
// try {
// FileOutputStream fos =
// new FileOutputStream(new File(jdkProxy.getClass().getName() +".class"));
// fos.write(proxyClassFile, 0, proxyClassFile.length);
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
 return jdkProxy;
}

 private static class JdkHandler implements InvocationHandler {

 final Object delegate;

 JdkHandler(Object delegate) {
 this.delegate = delegate;
}

 public Object invoke(Object object, Method method, Object[] objects) throws Throwable {
 return method.invoke(delegate, objects);
}
}

 private static CountService createCglibDynamicProxy(final CountService delegate) throws Exception {
 Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CountServiceImpl.class);
 enhancer.setCallback(new MethodInterceptor() {
@Override
 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
 return proxy.invokeSuper(obj, args);
}
});
 CountServiceImpl cglibProxy = (CountServiceImpl) enhancer.create();
 // 反汇编字节码用,测试的时候注释掉这段代码,不然影响测试结果
 // 下面一行代码参照net.sf.cglib.core.AbstractClassGenerator类中byte[] b = strategy.generate(this);
// byte[] proxyClassFile = new DefaultGeneratorStrategy().generate(enhancer);
// try {
// FileOutputStream fos =
// new FileOutputStream(new File(cglibProxy.getClass().getName() +".class"));
// fos.write(proxyClassFile, 0, proxyClassFile.length);
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
 return cglibProxy;
}
}
数据为执行三次,每次调用一千万次代理方法的结果  测试环境1:  JDK:fastdebug1.6 CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar CPU:P8400 2.53GHz 2.53GHz 测试结果1:
Create JDK Proxy: 13 ms
Create CGLIB Proxy: 201 ms
Run JDK Proxy: 1571 ms, 897,559 t/s
Run CGLIB Proxy: 824 ms, 1,711,244 t/s
-------------------
Run JDK Proxy: 1519 ms, 928,285 t/s
Run CGLIB Proxy: 576 ms, 2,448,030 t/s
-------------------
Run JDK Proxy: 1546 ms, 912,073 t/s
Run CGLIB Proxy: 590 ms, 2,389,941 t/s
-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢15倍,执行速度是JDK Proxy的2倍左右  测试环境2:  JDK:fastdebug1.7 CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar CPU:P8400 2.53GHz 2.53GHz 测试结果2:
Create JDK Proxy: 14 ms
Create CGLIB Proxy: 204 ms
Run JDK Proxy: 1608 ms, 876,906 t/s
Run CGLIB Proxy: 529 ms, 2,665,530 t/s
-------------------
Run JDK Proxy: 1591 ms, 886,276 t/s
Run CGLIB Proxy: 405 ms, 3,481,642 t/s
-------------------
Run JDK Proxy: 1624 ms, 868,266 t/s
Run CGLIB Proxy: 405 ms, 3,481,642 t/s
-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢15倍,执行速度是JDK Proxy的4倍左右  测试环境3:  JDK:jdk1.6.0_21 CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar CPU:P8400 2.53GHz 2.53GHz 测试结果3:
Create JDK Proxy: 8 ms
Create CGLIB Proxy: 99 ms
Run JDK Proxy: 911 ms, 1,547,821 t/s
Run CGLIB Proxy: 435 ms, 3,241,529 t/s
-------------------
Run JDK Proxy: 870 ms, 1,620,764 t/s
Run CGLIB Proxy: 399 ms, 3,533,998 t/s
-------------------
Run JDK Proxy: 894 ms, 1,577,254 t/s
Run CGLIB Proxy: 404 ms, 3,490,260 t/s
-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢10倍以上,执行速度是JDK Proxy的2倍左右  测试环境4:  JDK:jdk1.7.0_02 CGLIB:和spring2.0.6 使用同样的cglib-nodep-2.1_3.jar CPU:P8400 2.53GHz 2.53GHz 测试结果4:
Create JDK Proxy: 43 ms
Create CGLIB Proxy: 129 ms
Run JDK Proxy: 940 ms, 1,500,069 t/s
Run CGLIB Proxy: 299 ms, 4,715,937 t/s
-------------------
Run JDK Proxy: 921 ms, 1,531,015 t/s
Run CGLIB Proxy: 269 ms, 5,241,878 t/s
-------------------
Run JDK Proxy: 932 ms, 1,512,945 t/s
Run CGLIB Proxy: 265 ms, 5,321,001 t/s
-------------------
CGLIB创建代理对象速度大概比JDK Proxy慢3倍,执行速度是JDK Proxy的3倍以上  字节码比较:   把测试代码中被注释的部分打开,生成class文件后执行javap -c 类名   JDK动态代理生成的字节码
 public final int count() throws ;
Code:
 0: aload_0 
 1: getfield #16 // Field java/lang/reflect/Proxy.h:Ljava/lang/reflect/InvocationHandler;
 4: aload_0 
 5: getstatic #50 // Field m3:Ljava/lang/reflect/Method;
 8: aconst_null 
 9: invokeinterface #28, 4 // InterfaceMethod java/lang/reflect/InvocationHandler.invoke:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
 14: checkcast #52 // class java/lang/Integer
 17: invokevirtual #55 // Method java/lang/Integer.intValue:()I
 20: ireturn 
 21: athrow 
 22: astore_1 
 23: new #42 // class java/lang/reflect/UndeclaredThrowableException
 26: dup 
 27: aload_1 
 28: invokespecial #45 // Method java/lang/reflect/UndeclaredThrowableException."<init>":(Ljava/lang/Throwable;)V
 31: athrow 
 Exception table:
 from to target type
 0 21 21 Class java/lang/Error
 0 21 21 Class java/lang/RuntimeException
 0 21 22 Class java/lang/Throwable
CGLIB生成的字节码:
 public final int count();
Code:
 0: aload_0 
 1: getfield #37 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodInterceptor;
 4: dup 
 5: ifnonnull 17
 8: pop 
 9: aload_0 
 10: invokestatic #41 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V
 13: aload_0 
 14: getfield #37 // Field CGLIB$CALLBACK_0:Lnet/sf/cglib/proxy/MethodInterceptor;
 17: dup 
 18: ifnull 52
 21: aload_0 
 22: getstatic #43 // Field CGLIB$count$0$Method:Ljava/lang/reflect/Method;
 25: getstatic #45 // Field CGLIB$emptyArgs:[Ljava/lang/Object;
 28: getstatic #47 // Field CGLIB$count$0$Proxy:Lnet/sf/cglib/proxy/MethodProxy;
 31: invokeinterface #53, 5 // InterfaceMethod net/sf/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;
 36: dup 
 37: ifnonnull 45
 40: pop 
 41: iconst_0 
 42: goto 51
 45: checkcast #55 // class java/lang/Number
 48: invokevirtual #58 // Method java/lang/Number.intValue:()I
 51: ireturn 
 52: aload_0 
 53: invokespecial #35 // Method CountServiceImpl.count:()I
 56: ireturn 
### Spring AOP 中 JDK 动态代理CGLIB 的区别 #### 区别概述 JDK 动态代理主要依赖于 Java 内置的 `java.lang.reflect.Proxy` 类来创建代理对象,而这些代理对象必须实现一个或多个接口。这种方式适用于目标类实现了至少一个接口的情况[^1]。 相比之下,CGLIB 是一种高性能的字节码生成库,它可以在运行时扩展 Java 类并定义新的方法。对于那些没有提供任何接口的目标类来说,CGLIB 提供了一种有效的解决方案。通过继承原始类并重写其非最终的方法,CGLIB 能够实现代理功能[^2]。 #### 实现原理 - **JDK 动态代理** 当使用 JDK 动态代理时,实际是在内存中构建了一个实现了相同接口的新类实例,并在这个新实例上调用指定的方法前/后执行额外逻辑。此过程利用了反射机制,因此性能上可能会稍逊一些,尤其是在频繁调用的情况下[^3]。 ```java // 创建 InvocationHandler 来处理方法调用 InvocationHandler handler = new MyInvocationHandler(target); // 获取被代理对象所实现的所有接口 Class<?>[] interfaces = target.getClass().getInterfaces(); // 返回由给定加载器接口数组构造的一个代理类的新实例 return Proxy.newProxyInstance(loader, interfaces, handler); ``` - **CGLIB** 对于未实现接口的对象,则采用 CGLIB 库来进行代理操作。CGLIB 可以直接子类化现有类,并覆盖其中的方法以便插入自定义行为。由于不需要借助接口,所以适用范围更广;不过需要注意的是,如果原类中有 final 方法则无法被覆写,也就意味着这部分不会受到 AOP 切面的影响[^4]。 ```java Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Target.class); // 设置要代理的父类 enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 执行前置通知或其他业务逻辑... Object result = proxy.invokeSuper(obj, args); // 调用父类方法 // 执行后置通知或其他业务逻辑... return result; } }); Target proxy = (Target) enhancer.create(); // 创建代理对象 ``` #### 性能对比 通常情况下,CGLIB 在某些特定场景下可能比 JDK 动态代理表现得更好,特别是在大量实例化的环境中。然而,在大多数应用场景里两者之间的差异并不明显,除非有非常严格的性能需求才需考虑这一点。另外值得注意的是,随着 JVM 编译优化的进步,这种差距正在逐渐缩小。 #### 使用场景建议 - 如果应用程序中的服务层组件都遵循良好的面向接口编程原则(即每个具体的服务都有对应的接口),那么推荐优先选用 JDK 动态代理方式。 - 若遇到确实存在不带接口的具体类需要加入到 AOP 处理链路之中,此时应该选择 CGLIB 方案作为替代方案之一。 - 还有一点很重要,当涉及到对私有成员变量的操作或是希望避免因修改原有代码结构带来的风险时,也可以倾向于使用 CGLIB 技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值