diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java
index eff97bda8b3..fefd5d9b520 100644
--- a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java
+++ b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java
@@ -16,7 +16,6 @@
package org.springframework.test.context.aot;
-import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
@@ -44,14 +43,12 @@ import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.SmartContextLoader;
import org.springframework.test.context.TestContextBootstrapper;
-import org.springframework.test.context.web.WebMergedContextConfiguration;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_CONSTRUCTORS;
import static org.springframework.aot.hint.MemberCategory.INVOKE_PUBLIC_METHODS;
-import static org.springframework.util.ResourceUtils.CLASSPATH_URL_PREFIX;
/**
* {@code TestContextAotGenerator} generates AOT artifacts for integration tests
@@ -63,8 +60,6 @@ import static org.springframework.util.ResourceUtils.CLASSPATH_URL_PREFIX;
*/
public class TestContextAotGenerator {
- private static final String SLASH = "/";
-
private static final Log logger = LogFactory.getLog(TestContextAotGenerator.class);
private final ApplicationContextAotGenerator aotGenerator = new ApplicationContextAotGenerator();
@@ -124,7 +119,6 @@ public class TestContextAotGenerator {
mergedConfigMappings.forEach((mergedConfig, testClasses) -> {
logger.debug(LogMessage.format("Generating AOT artifacts for test classes %s",
testClasses.stream().map(Class::getName).toList()));
- registerHintsForMergedConfig(mergedConfig);
try {
this.testRuntimeHintsRegistrars.forEach(registrar -> registrar.registerHints(this.runtimeHints,
mergedConfig, Collections.unmodifiableList(testClasses), getClass().getClassLoader()));
@@ -247,51 +241,6 @@ public class TestContextAotGenerator {
.registerType(TypeReference.of(className), INVOKE_PUBLIC_METHODS);
}
- private void registerHintsForMergedConfig(MergedContextConfiguration mergedConfig) {
- // @ContextConfiguration(loader = ...)
- ContextLoader contextLoader = mergedConfig.getContextLoader();
- if (contextLoader != null) {
- registerDeclaredConstructors(contextLoader.getClass());
- }
-
- // @ContextConfiguration(initializers = ...)
- mergedConfig.getContextInitializerClasses().forEach(this::registerDeclaredConstructors);
-
- // @ContextConfiguration(locations = ...)
- registerHintsForClasspathResources(mergedConfig.getLocations());
-
- // @TestPropertySource(locations = ... )
- registerHintsForClasspathResources(mergedConfig.getPropertySourceLocations());
-
- if (mergedConfig instanceof WebMergedContextConfiguration webMergedConfig) {
- String resourceBasePath = webMergedConfig.getResourceBasePath();
- if (resourceBasePath.startsWith(CLASSPATH_URL_PREFIX)) {
- String pattern = resourceBasePath.substring(CLASSPATH_URL_PREFIX.length());
- if (!pattern.startsWith(SLASH)) {
- pattern = SLASH + pattern;
- }
- if (!pattern.endsWith(SLASH)) {
- pattern += SLASH;
- }
- pattern += "*";
- this.runtimeHints.resources().registerPattern(pattern);
- }
- }
- }
-
- private void registerHintsForClasspathResources(String... locations) {
- Arrays.stream(locations)
- .filter(location -> location.startsWith(CLASSPATH_URL_PREFIX))
- .map(location -> {
- location = location.substring(CLASSPATH_URL_PREFIX.length());
- if (!location.startsWith(SLASH)) {
- location = SLASH + location;
- }
- return location;
- })
- .forEach(this.runtimeHints.resources()::registerPattern);
- }
-
private void registerDeclaredConstructors(Class> type) {
ReflectionHints reflectionHints = this.runtimeHints.reflection();
reflectionHints.registerType(type, INVOKE_DECLARED_CONSTRUCTORS);
diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java b/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java
new file mode 100644
index 00000000000..4f93602ed3c
--- /dev/null
+++ b/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ * 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.test.context.aot.hint;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.test.context.ContextLoader;
+import org.springframework.test.context.MergedContextConfiguration;
+import org.springframework.test.context.aot.TestRuntimeHintsRegistrar;
+import org.springframework.test.context.web.WebMergedContextConfiguration;
+
+import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_CONSTRUCTORS;
+import static org.springframework.util.ResourceUtils.CLASSPATH_URL_PREFIX;
+
+/**
+ * {@link TestRuntimeHintsRegistrar} implementation that registers run-time hints
+ * for standard functionality in the Spring TestContext Framework.
+ *
+ * @author Sam Brannen
+ * @since 6.0
+ * @see TestContextRuntimeHints
+ */
+class StandardTestRuntimeHints implements TestRuntimeHintsRegistrar {
+
+ private static final String SLASH = "/";
+
+
+ @Override
+ public void registerHints(RuntimeHints runtimeHints, MergedContextConfiguration mergedConfig,
+ List> testClasses, ClassLoader classLoader) {
+
+ registerHintsForMergedContextConfiguration(runtimeHints, mergedConfig);
+ }
+
+ private void registerHintsForMergedContextConfiguration(
+ RuntimeHints runtimeHints, MergedContextConfiguration mergedConfig) {
+
+ // @ContextConfiguration(loader = ...)
+ ContextLoader contextLoader = mergedConfig.getContextLoader();
+ if (contextLoader != null) {
+ registerDeclaredConstructors(runtimeHints, contextLoader.getClass());
+ }
+
+ // @ContextConfiguration(initializers = ...)
+ mergedConfig.getContextInitializerClasses()
+ .forEach(clazz -> registerDeclaredConstructors(runtimeHints, clazz));
+
+ // @ContextConfiguration(locations = ...)
+ registerClasspathResources(runtimeHints, mergedConfig.getLocations());
+
+ // @TestPropertySource(locations = ... )
+ registerClasspathResources(runtimeHints, mergedConfig.getPropertySourceLocations());
+
+ // @WebAppConfiguration(value = ...)
+ if (mergedConfig instanceof WebMergedContextConfiguration webConfig) {
+ registerClasspathResourceDirectoryStructure(runtimeHints, webConfig.getResourceBasePath());
+ }
+ }
+
+ private void registerDeclaredConstructors(RuntimeHints runtimeHints, Class> type) {
+ runtimeHints.reflection().registerType(type, INVOKE_DECLARED_CONSTRUCTORS);
+ }
+
+ private void registerClasspathResources(RuntimeHints runtimeHints, String... locations) {
+ Arrays.stream(locations)
+ .filter(location -> location.startsWith(CLASSPATH_URL_PREFIX))
+ .map(this::cleanClasspathResource)
+ .forEach(runtimeHints.resources()::registerPattern);
+ }
+
+ private void registerClasspathResourceDirectoryStructure(RuntimeHints runtimeHints, String directory) {
+ if (directory.startsWith(CLASSPATH_URL_PREFIX)) {
+ String pattern = cleanClasspathResource(directory);
+ if (!pattern.endsWith(SLASH)) {
+ pattern += SLASH;
+ }
+ pattern += "*";
+ runtimeHints.resources().registerPattern(pattern);
+ }
+ }
+
+ private String cleanClasspathResource(String location) {
+ location = location.substring(CLASSPATH_URL_PREFIX.length());
+ if (!location.startsWith(SLASH)) {
+ location = SLASH + location;
+ }
+ return location;
+ }
+
+}
diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/hint/TestContextRuntimeHints.java b/spring-test/src/main/java/org/springframework/test/context/aot/hint/TestContextRuntimeHints.java
index d1ceaa6b54d..58f34cc1b8f 100644
--- a/spring-test/src/main/java/org/springframework/test/context/aot/hint/TestContextRuntimeHints.java
+++ b/spring-test/src/main/java/org/springframework/test/context/aot/hint/TestContextRuntimeHints.java
@@ -34,6 +34,7 @@ import org.springframework.util.ClassUtils;
*
* @author Sam Brannen
* @since 6.0
+ * @see StandardTestRuntimeHints
*/
class TestContextRuntimeHints implements RuntimeHintsRegistrar {
diff --git a/spring-test/src/main/resources/META-INF/spring/aot.factories b/spring-test/src/main/resources/META-INF/spring/aot.factories
index 3a0242dec41..dcedd2c64e2 100644
--- a/spring-test/src/main/resources/META-INF/spring/aot.factories
+++ b/spring-test/src/main/resources/META-INF/spring/aot.factories
@@ -1,2 +1,5 @@
org.springframework.aot.hint.RuntimeHintsRegistrar=\
org.springframework.test.context.aot.hint.TestContextRuntimeHints
+
+org.springframework.test.context.aot.TestRuntimeHintsRegistrar=\
+org.springframework.test.context.aot.hint.StandardTestRuntimeHints
\ No newline at end of file