🎉🎉《Spring Boot实战案例合集》目前已更新131个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. 简介
首先,我们先来看段Spring MVC底层在实现调用Controller对应接口方法的实现:
public class InvocableHandlerMethod extends HandlerMethod {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种方法进行性能测试(与原始反射进行对象),下面是完整的测试代码:
public class MethodHandleTest {private MethodHandle sayHelloHandle ;private Method method ;private MethodHandleTest instance ;private MethodInvoker invoker ;public void sayHello(String name) {String s = "Hello, " + name ;}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);}// 使用MethodHandlepublic void methodHandle() {sayHelloHandle.invokeExact(instance, "World");}// 使用反射public void methodReflect() throws Exception {method.invoke(instance, "World") ;}// 普通方法调用public void methodNormal() {instance.sayHello("World") ;}// 使用bytebuddypublic 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种方案进行改进反射的调用。


