From ec2a54f203a0babc6644d2c834f03681d608c912 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 8 Apr 2022 13:02:36 +0200 Subject: [PATCH] Consistent fallback in case of fast-class generation failure Closes gh-28138 (cherry picked from commit 7aed6279a284283f079290f44c5d0eee7bef7cda) --- .../aop/framework/Cglib2AopProxy.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java b/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java index 46ed66b90490..65b3f5c4b65f 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -328,7 +328,23 @@ private Callback[] getCallbacks(Class rootClass) throws Exception { } /** - * Wrap a return of this if necessary to be the proxy + * Invoke the given method with a CGLIB MethodProxy if possible, falling back + * to a plain reflection invocation in case of a fast-class generation failure. + */ + private static Object invokeMethod(Object target, Method method, Object[] args, MethodProxy methodProxy) + throws Throwable { + try { + return methodProxy.invoke(target, args); + } + catch (CodeGenerationException ex) { + logger.warn("Unable to fast-class invoke method [" + method + "] on target [" + target + "]. Falling back to reflection."); + return AopUtils.invokeJoinpointUsingReflection(target, method, args); + } + } + + /** + * Process a return value. Wraps a return of {@code this} if necessary to be the + * {@code proxy} and also verifies that {@code null} is not returned as a primitive. */ private static Object massageReturnTypeIfNecessary(Object proxy, Object target, Method method, Object retVal) { // Massage return value if necessary @@ -378,7 +394,7 @@ public StaticUnadvisedInterceptor(Object target) { } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { - Object retVal = methodProxy.invoke(this.target, args); + Object retVal = invokeMethod(this.target, method, args, methodProxy); return massageReturnTypeIfNecessary(proxy, this.target, method, retVal); } } @@ -400,7 +416,7 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy Object oldProxy = null; try { oldProxy = AopContext.setCurrentProxy(proxy); - Object retVal = methodProxy.invoke(this.target, args); + Object retVal = invokeMethod(this.target, method, args, methodProxy); return massageReturnTypeIfNecessary(proxy, this.target, method, retVal); } finally { @@ -426,7 +442,7 @@ public DynamicUnadvisedInterceptor(TargetSource targetSource) { public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object target = this.targetSource.getTarget(); try { - Object retVal = methodProxy.invoke(target, args); + Object retVal = invokeMethod(target, method, args, methodProxy); return massageReturnTypeIfNecessary(proxy, target, method, retVal); } finally { @@ -452,7 +468,7 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy Object target = this.targetSource.getTarget(); try { oldProxy = AopContext.setCurrentProxy(proxy); - Object retVal = methodProxy.invoke(target, args); + Object retVal = invokeMethod(target, method, args, methodProxy); return massageReturnTypeIfNecessary(proxy, target, method, retVal); } finally { @@ -615,7 +631,8 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy // Note that the final invoker must be an InvokerInterceptor, so we know // it does nothing but a reflective operation on the target, and no hot // swapping or fancy proxying. - retVal = methodProxy.invoke(target, args); + Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); + retVal = invokeMethod(target, method, argsToUse, methodProxy); } else { // We need to create a method invocation...