AopUtils.getMostSpecificMethod does not return original method for proxy-derived method anymore #32365
Description
Affects: 5.3.30, 5.3.31, 5.3.32
Since 5.3.30 AopUtils.getMostSpecificMethod
is no longer giving the correct result in our code. The problem was introduced in recent changes to ClassUtils.getMostSpecificMethod
in the check to determine if the method is overridable and to only continue the search if it is - if it is not overridable then it is assumed that it is already the most specific method and returns it. However, this is not the correct logic in some cases.
In our case the method passed in comes from a runtime-generated Proxy and we use this util to get the original method (with generic params intact). This generated method appears to have a final
modifier - thus is not considered overridable by the new code. I don't think this is the correct logic as the original method is in fact overridable - it has been overriden by the generated method. Previously, the final
modifier was not considered so the logic was effectively "this method could not have been overriden". Now, the logic is "this method cannot be overriden further".
Minimal test case (passes on 5.3.29, fails on 5.3.30+):
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
public class AopTest {
interface I {
void f(List<String> a);
}
static class C implements I {
public void f(List<String> a) {
}
}
@Test
public void aopMostSpecificMethod() throws Exception {
final C c = new C();
final ProxyFactory proxyFactory = new ProxyFactory(c);
final I proxy = (I) proxyFactory.getProxy();
final Type paramType = AopUtils.getMostSpecificMethod(
proxy.getClass().getMethod("f", List.class),
AopUtils.getTargetClass(proxy)).getParameters()[0].getParameterizedType();
assertTrue(paramType instanceof ParameterizedType);
assertEquals(String.class, ((ParameterizedType) paramType).getActualTypeArguments()[0]);
}
}