From 8e5cad2af3d0465c98f7269ec1a6262a3f30c1bb Mon Sep 17 00:00:00 2001 From: stsypanov Date: Mon, 30 Dec 2019 17:20:07 +0200 Subject: [PATCH] Add fast path for ClassUtils.hasMethod() --- .../aop/framework/CglibAopProxy.java | 2 +- .../beans/factory/support/AutowireUtils.java | 5 ++- .../InterfaceBasedMBeanInfoAssembler.java | 2 +- .../MethodValidationInterceptor.java | 2 +- .../org/springframework/util/ClassUtils.java | 34 +++++++++++++++---- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java index 1e899671aaaf..a58ae43ced75 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java @@ -365,7 +365,7 @@ public int hashCode() { */ private static boolean implementsInterface(Method method, Set> ifcs) { for (Class ifc : ifcs) { - if (ClassUtils.hasMethod(ifc, method.getName(), method.getParameterTypes())) { + if (ClassUtils.hasMethod(ifc, method)) { return true; } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java index 50adef4df217..cb569b07d626 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java @@ -97,7 +97,7 @@ public static boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) { // It was declared by CGLIB, but we might still want to autowire it // if it was actually declared by the superclass. Class superclass = wm.getDeclaringClass().getSuperclass(); - return !ClassUtils.hasMethod(superclass, wm.getName(), wm.getParameterTypes()); + return !ClassUtils.hasMethod(superclass, wm); } /** @@ -112,8 +112,7 @@ public static boolean isSetterDefinedInInterface(PropertyDescriptor pd, Set targetClass = setter.getDeclaringClass(); for (Class ifc : interfaces) { - if (ifc.isAssignableFrom(targetClass) && - ClassUtils.hasMethod(ifc, setter.getName(), setter.getParameterTypes())) { + if (ifc.isAssignableFrom(targetClass) && ClassUtils.hasMethod(ifc, setter)) { return true; } } diff --git a/spring-context/src/main/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssembler.java b/spring-context/src/main/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssembler.java index 8248215725aa..3b4ef961f6ed 100644 --- a/spring-context/src/main/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssembler.java +++ b/spring-context/src/main/java/org/springframework/jmx/export/assembler/InterfaceBasedMBeanInfoAssembler.java @@ -207,7 +207,7 @@ protected boolean includeOperation(Method method, String beanKey) { * configured interfaces and is public, otherwise {@code false}. */ private boolean isPublicInInterface(Method method, String beanKey) { - return ((method.getModifiers() & Modifier.PUBLIC) > 0) && isDeclaredInInterface(method, beanKey); + return Modifier.isPublic(method.getModifiers()) && isDeclaredInInterface(method, beanKey); } /** diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java index 4b4d5e506a47..eb28c85d8506 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/MethodValidationInterceptor.java @@ -145,7 +145,7 @@ else if (FactoryBean.class.isAssignableFrom(clazz)) { factoryBeanType = FactoryBean.class; } return (factoryBeanType != null && !method.getName().equals("getObject") && - ClassUtils.hasMethod(factoryBeanType, method.getName(), method.getParameterTypes())); + ClassUtils.hasMethod(factoryBeanType, method)); } /** diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 44390ec2dfd1..c77dcba127fd 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -1101,6 +1101,24 @@ public static boolean hasMethod(Class clazz, String methodName, Class... p return (getMethodIfAvailable(clazz, methodName, paramTypes) != null); } + /** + * Determine whether the given class has a public method with the given signature. + * @param clazz the clazz to analyze + * @param method checked method + * @return whether the class has a corresponding method + * @see Method#getDeclaringClass + */ + public static boolean hasMethod(Class clazz, Method method) { + Assert.notNull(clazz, "Class must not be null"); + Assert.notNull(method, "Method must not be null"); + if (clazz == method.getDeclaringClass()) { + return true; + } + String methodName = method.getName(); + Class[] paramTypes = method.getParameterTypes(); + return getMethodOrNull(clazz, methodName, paramTypes) != null; + } + /** * Determine whether the given class has a public method with the given signature, * and return it if available (else throws an {@code IllegalStateException}). @@ -1158,12 +1176,7 @@ public static Method getMethodIfAvailable(Class clazz, String methodName, @Nu Assert.notNull(clazz, "Class must not be null"); Assert.notNull(methodName, "Method name must not be null"); if (paramTypes != null) { - try { - return clazz.getMethod(methodName, paramTypes); - } - catch (NoSuchMethodException ex) { - return null; - } + return getMethodOrNull(clazz, methodName, paramTypes); } else { Set candidates = findMethodCandidatesByName(clazz, methodName); @@ -1370,4 +1383,13 @@ private static Set findMethodCandidatesByName(Class clazz, String met } return candidates; } + + @Nullable + private static Method getMethodOrNull(Class clazz, String methodName, Class[] paramTypes) { + try { + return clazz.getMethod(methodName, paramTypes); + } catch (NoSuchMethodException ex) { + return null; + } + } }