diff --git a/spring-core/src/main/java/org/springframework/core/MethodIntrospector.java b/spring-core/src/main/java/org/springframework/core/MethodIntrospector.java index 9f905cbda47..f1ceac4a7cc 100644 --- a/spring-core/src/main/java/org/springframework/core/MethodIntrospector.java +++ b/spring-core/src/main/java/org/springframework/core/MethodIntrospector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -36,6 +36,7 @@ import org.springframework.util.ReflectionUtils; * * @author Juergen Hoeller * @author Rossen Stoyanchev + * @author Sam Brannen * @since 4.2.3 */ public final class MethodIntrospector { @@ -75,6 +76,7 @@ public final class MethodIntrospector { if (result != null) { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); if (bridgedMethod == specificMethod || bridgedMethod == method || + bridgedMethod.equals(specificMethod) || bridgedMethod.equals(method) || metadataLookup.inspect(bridgedMethod) == null) { methodMap.put(specificMethod, result); } 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 062a386c397..003da863f3b 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -305,7 +305,7 @@ public abstract class ClassUtils { } catch (ClassNotFoundException ex) { int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR); - int previousDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR, lastDotIndex -1); + int previousDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR, lastDotIndex - 1); if (lastDotIndex != -1 && previousDotIndex != -1 && Character.isUpperCase(name.charAt(previousDotIndex + 1))) { String nestedClassName = name.substring(0, lastDotIndex) + NESTED_CLASS_SEPARATOR + name.substring(lastDotIndex + 1); diff --git a/spring-core/src/test/java/a/ClassHavingNestedClass.java b/spring-core/src/test/java/a/ClassHavingNestedClass.java index b18d8b05878..2170cdcd860 100644 --- a/spring-core/src/test/java/a/ClassHavingNestedClass.java +++ b/spring-core/src/test/java/a/ClassHavingNestedClass.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -19,6 +19,9 @@ package a; /** * Test class for {@code org.springframework.util.ClassUtilsTests}. * + *
The use case for this test class requires that the package name is a single
+ * character (i.e., length of 1).
+ *
* @author Johnny Lim
*/
public class ClassHavingNestedClass {
diff --git a/spring-core/src/test/java/org/springframework/core/MethodIntrospectorTests.java b/spring-core/src/test/java/org/springframework/core/MethodIntrospectorTests.java
new file mode 100644
index 00000000000..f11f8eb8659
--- /dev/null
+++ b/spring-core/src/test/java/org/springframework/core/MethodIntrospectorTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2002-2024 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.core.MethodIntrospector.MetadataLookup;
+import org.springframework.core.annotation.MergedAnnotations;
+import org.springframework.util.ReflectionUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.core.annotation.MergedAnnotations.SearchStrategy.TYPE_HIERARCHY;
+
+/**
+ * Tests for {@link MethodIntrospector}.
+ *
+ * @author Sam Brannen
+ * @since 5.3.34
+ */
+class MethodIntrospectorTests {
+
+ @Test // gh-32586
+ void selectMethodsAndClearDeclaredMethodsCacheBetweenInvocations() {
+ Class> targetType = ActualController.class;
+
+ // Preconditions for this use case.
+ assertThat(targetType).isPublic();
+ assertThat(targetType.getSuperclass()).isPackagePrivate();
+
+ MetadataLookup