大数跨境
0
0

性能优化!3种方案优化Controller接口调用,性能提升N倍

性能优化!3种方案优化Controller接口调用,性能提升N倍 Spring全家桶实战案例
2025-06-06
0
导读:性能优化!3种方案优化Controller接口调用,性能提升N倍
Spring Boot 3实战案例锦集PDF电子书已更新至100篇!
图片

🎉🎉《Spring Boot实战案例合集》目前已更新131个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

首先,我们先来看段Spring MVC底层在实现调用Controller对应接口方法的实现:

public class InvocableHandlerMethod extends HandlerMethod {  @Nullable  protected Object doInvoke(Object... args) throws Exception {    Method method = getBridgedMethod();    try {      return method.invoke(getBean(), args);    }  }}

以上代码是当用户请求Controller对应的接口时,底层默认采用Java反射机制来实现方法的动态调用。这种机制虽然灵活,但在高并发场景下可能成为性能瓶颈。

针对Controller接口调用的反射调用瓶颈,本篇文章将通过三种进行优化,从而提升接口调用性能。方案如下:

  • 引入CGLIB的FastClass机制,它通过生成字节码直接调用方法,绕过了反射的开销。

  • 采用ByteBuddy动态生成代理类,进一步优化方法调用路径,减少运行时开销。

  • 使用MethodHandle这一Java 7引入的新特性,它提供了更高效、类型安全的方法调用方式。

通过这三种优化方案,有效解决了反射调用带来的性能瓶颈问题,为高并发场景下的系统稳定性和响应速度提供了有力保障。

下面我们先通过JMH对以上3种方法进行性能测试(与原始反射进行对象),下面是完整的测试代码:

@Warmup(iterations = 3, time = 1)@Fork(value = 1, jvmArgsAppend = {"-Xms512m", "-Xmx512m"})@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)@State(Scope.Benchmark)@Threads(1)public class MethodHandleTest {
  private MethodHandle sayHelloHandle ;  private Method method ;  private MethodHandleTest instance ;  private MethodInvoker invoker ;
  public void sayHello(String name) {    String s = "Hello, " + name ;   }
  @Setup  public void init() throws Exception {    MethodHandles.Lookup lookup = MethodHandles.lookup();    MethodType methodType = MethodType.methodType(void.class, String.class);    sayHelloHandle = lookup.findVirtual(MethodHandleTest.class, "sayHello", methodType);    method = MethodHandleTest.class.getDeclaredMethod("sayHello", String.class) ;    instance = new MethodHandleTest() ;     invoker = InvokerGenerator.generateInvoker(method);  }  // 使用MethodHandle  @Benchmark  public void methodHandle() {    sayHelloHandle.invokeExact(instance, "World");  }  // 使用反射  @Benchmark  public void methodReflect() throws Exception {    method.invoke(instance, "World") ;  }  // 普通方法调用  @Benchmark  public void methodNormal() {    instance.sayHello("World") ;  }  // 使用bytebuddy  @Benchmark  public void bytebuddy() throws Throwable {    invoker.invoke(instance, new Object[] {"World"}) ;  }  public static void main(String[] args) throws Exception {    Options options = new OptionsBuilder()        .include(MethodHandleTest.class.getSimpleName())        .forks(1).build();    new Runner(options).run();  }}

测试结果如下:

通过测试结果得知:反射性能最低,其次是MethodHandle,再下来是bytebuddy,性能最佳正常调用(普通方法调用);不过bytebuddy基本接近普通方法调用了。

接下来,我们分别通过上面的3种方案进行改进反射的调用。

2.实战案例

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读285
粉丝0
内容832