Skip to content

Commit 2c8b7fe

Browse files
committed
ClassUtils.getMostSpecificMethod uses Class.getMethod code path in case of a public method
This should be significantly faster than our standard algorithm, for a very common case. Motivated by SPR-9802, even if the fix there uses a different approach, with transaction name determination not calling getMostSpecificMethod at all anymore. Issue: SPR-9802
1 parent bbfc807 commit 2c8b7fe

File tree

1 file changed

+35
-14
lines changed
  • org.springframework.core/src/main/java/org/springframework/util

1 file changed

+35
-14
lines changed

org.springframework.core/src/main/java/org/springframework/util/ClassUtils.java

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -462,17 +462,28 @@ public static String getClassFileName(Class<?> clazz) {
462462
}
463463

464464
/**
465-
* Determine the name of the package of the given class:
466-
* e.g. "java.lang" for the <code>java.lang.String</code> class.
465+
* Determine the name of the package of the given class,
466+
* e.g. "java.lang" for the {@code java.lang.String} class.
467467
* @param clazz the class
468468
* @return the package name, or the empty String if the class
469469
* is defined in the default package
470470
*/
471471
public static String getPackageName(Class<?> clazz) {
472472
Assert.notNull(clazz, "Class must not be null");
473-
String className = clazz.getName();
474-
int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);
475-
return (lastDotIndex != -1 ? className.substring(0, lastDotIndex) : "");
473+
return getPackageName(clazz.getName());
474+
}
475+
476+
/**
477+
* Determine the name of the package of the given fully-qualified class name,
478+
* e.g. "java.lang" for the {@code java.lang.String} class name.
479+
* @param fqClassName the fully-qualified class name
480+
* @return the package name, or the empty String if the class
481+
* is defined in the default package
482+
*/
483+
public static String getPackageName(String fqClassName) {
484+
Assert.notNull(fqClassName, "Class name must not be null");
485+
int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR);
486+
return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : "");
476487
}
477488

478489
/**
@@ -713,7 +724,7 @@ public static boolean hasAtLeastOneMethodWithName(Class<?> clazz, String methodN
713724
* Call {@link org.springframework.core.BridgeMethodResolver#findBridgedMethod}
714725
* if bridge method resolution is desirable (e.g. for obtaining metadata from
715726
* the original method definition).
716-
* <p><b>NOTE:</b>Since Spring 3.1.1, if java security settings disallow reflective
727+
* <p><b>NOTE:</b> Since Spring 3.1.1, if Java security settings disallow reflective
717728
* access (e.g. calls to {@code Class#getDeclaredMethods} etc, this implementation
718729
* will fall back to returning the originally provided method.
719730
* @param method the method to be invoked, which may come from an interface
@@ -723,17 +734,28 @@ public static boolean hasAtLeastOneMethodWithName(Class<?> clazz, String methodN
723734
* <code>targetClass</code> doesn't implement it or is <code>null</code>
724735
*/
725736
public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
726-
Method specificMethod = null;
727737
if (method != null && isOverridable(method, targetClass) &&
728738
targetClass != null && !targetClass.equals(method.getDeclaringClass())) {
729739
try {
730-
specificMethod = ReflectionUtils.findMethod(targetClass, method.getName(), method.getParameterTypes());
731-
} catch (AccessControlException ex) {
732-
// security settings are disallowing reflective access; leave
733-
// 'specificMethod' null and fall back to 'method' below
740+
if (Modifier.isPublic(method.getModifiers())) {
741+
try {
742+
return targetClass.getMethod(method.getName(), method.getParameterTypes());
743+
}
744+
catch (NoSuchMethodException ex) {
745+
return method;
746+
}
747+
}
748+
else {
749+
Method specificMethod =
750+
ReflectionUtils.findMethod(targetClass, method.getName(), method.getParameterTypes());
751+
return (specificMethod != null ? specificMethod : method);
752+
}
753+
}
754+
catch (AccessControlException ex) {
755+
// Security settings are disallowing reflective access; fall back to 'method' below.
734756
}
735757
}
736-
return (specificMethod != null ? specificMethod : method);
758+
return method;
737759
}
738760

739761
/**
@@ -1139,5 +1161,4 @@ public static boolean isCglibProxyClassName(String className) {
11391161
return (className != null && className.contains(CGLIB_CLASS_SEPARATOR));
11401162
}
11411163

1142-
11431164
}

0 commit comments

Comments
 (0)