Skip to content

Commit e421104

Browse files
committed
Supply RuntimeHints to an AotContextLoader
This commit introduces a new loadContextForAotProcessing(...) variant in AotContextLoader which accepts a RuntimeHints argument. This new method is an interface default method which delegates to the existing loadContextForAotProcessing(MergedContextConfiguration) variant for backward compatibility. In addition, the original loadContextForAotProcessing(...) variant is now deprecated and has been converted to an interface default method which throws an UnsupportedOperationException. Note, however, that the framework now only invokes the new loadContextForAotProcessing(...) variant within TestContextAotGenerator. Closes gh-34513
1 parent adfeba2 commit e421104

10 files changed

+396
-17
lines changed

spring-test/src/main/java/org/springframework/test/context/aot/AotContextLoader.java

+41-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.test.context.aot;
1818

19+
import org.springframework.aot.hint.RuntimeHints;
1920
import org.springframework.context.ApplicationContext;
2021
import org.springframework.context.ApplicationContextInitializer;
2122
import org.springframework.context.ConfigurableApplicationContext;
@@ -25,9 +26,9 @@
2526

2627
/**
2728
* Strategy interface for loading an {@link ApplicationContext} for build-time
28-
* {@linkplain #loadContextForAotProcessing AOT processing} as well as run-time
29-
* {@linkplain #loadContextForAotRuntime AOT execution} for an integration test
30-
* managed by the Spring TestContext Framework.
29+
* {@linkplain #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
30+
* AOT processing} as well as run-time {@linkplain #loadContextForAotRuntime
31+
* AOT execution} for an integration test managed by the Spring TestContext Framework.
3132
*
3233
* <p>{@code AotContextLoader} is an extension of the {@link SmartContextLoader}
3334
* SPI that allows a context loader to optionally provide ahead-of-time (AOT)
@@ -42,6 +43,30 @@
4243
*/
4344
public interface AotContextLoader extends SmartContextLoader {
4445

46+
/**
47+
* Load a new {@link ApplicationContext} for AOT build-time processing based
48+
* on the supplied {@link MergedContextConfiguration}, configure the context,
49+
* and return the context.
50+
* <p>The default implementation of this method throws an
51+
* {@link UnsupportedOperationException}. Note, however, that the framework
52+
* invokes {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)}
53+
* as of Spring Framework 6.2.4.
54+
* @param mergedConfig the merged context configuration to use to load the
55+
* application context
56+
* @return a new {@code GenericApplicationContext}
57+
* @throws ContextLoadException if context loading failed
58+
* @see #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
59+
* @see #loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
60+
* @deprecated as of Spring Framework 6.2.4, in favor of
61+
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
62+
* to be removed in Spring Framework 8.0
63+
*/
64+
@Deprecated(since = "6.2.4", forRemoval = true)
65+
default ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
66+
throw new UnsupportedOperationException(
67+
"Invoke loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints) instead");
68+
}
69+
4570
/**
4671
* Load a new {@link ApplicationContext} for AOT build-time processing based
4772
* on the supplied {@link MergedContextConfiguration}, configure the context,
@@ -65,13 +90,23 @@ public interface AotContextLoader extends SmartContextLoader {
6590
* throw new ContextLoadException(context, ex);
6691
* }
6792
* </pre>
93+
* <p>For backward compatibility, the default implementation of this method
94+
* delegates to {@link #loadContextForAotProcessing(MergedContextConfiguration)}.
95+
* Note, however, that the framework only invokes this method as of Spring
96+
* Framework 6.2.4.
6897
* @param mergedConfig the merged context configuration to use to load the
6998
* application context
99+
* @param runtimeHints the runtime hints
70100
* @return a new {@code GenericApplicationContext}
71101
* @throws ContextLoadException if context loading failed
102+
* @since 6.2.4
72103
* @see #loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
73104
*/
74-
ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception;
105+
default ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
106+
RuntimeHints runtimeHints) throws Exception {
107+
108+
return loadContextForAotProcessing(mergedConfig);
109+
}
75110

76111
/**
77112
* Load a new {@link ApplicationContext} for AOT run-time execution based on
@@ -98,7 +133,7 @@ public interface AotContextLoader extends SmartContextLoader {
98133
* be applied to the context in order to recreate bean definitions
99134
* @return a new {@code GenericApplicationContext}
100135
* @throws ContextLoadException if context loading failed
101-
* @see #loadContextForAotProcessing(MergedContextConfiguration)
136+
* @see #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
102137
*/
103138
ApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
104139
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception;

spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -331,7 +331,7 @@ ClassName processAheadOfTime(MergedContextConfiguration mergedConfig,
331331
* create {@link GenericApplicationContext GenericApplicationContexts}.
332332
* @throws TestContextAotException if an error occurs while loading the application
333333
* context or if one of the prerequisites is not met
334-
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
334+
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
335335
*/
336336
private GenericApplicationContext loadContextForAotProcessing(
337337
MergedContextConfiguration mergedConfig) throws TestContextAotException {
@@ -345,7 +345,7 @@ private GenericApplicationContext loadContextForAotProcessing(
345345

346346
if (contextLoader instanceof AotContextLoader aotContextLoader) {
347347
try {
348-
ApplicationContext context = aotContextLoader.loadContextForAotProcessing(mergedConfig);
348+
ApplicationContext context = aotContextLoader.loadContextForAotProcessing(mergedConfig, this.runtimeHints);
349349
if (context instanceof GenericApplicationContext gac) {
350350
return gac;
351351
}

spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -19,6 +19,7 @@
1919
import org.apache.commons.logging.Log;
2020
import org.apache.commons.logging.LogFactory;
2121

22+
import org.springframework.aot.hint.RuntimeHints;
2223
import org.springframework.context.ApplicationContext;
2324
import org.springframework.context.ApplicationContextInitializer;
2425
import org.springframework.context.ConfigurableApplicationContext;
@@ -225,8 +226,13 @@ public final ApplicationContext loadContext(MergedContextConfiguration mergedCon
225226
* {@code ApplicationContext} from the supplied merged context configuration
226227
* @since 6.0
227228
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
229+
* @deprecated as of Spring Framework 6.2.4, in favor of
230+
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
231+
* to be removed in Spring Framework 8.0
228232
*/
233+
@Deprecated(since = "6.2.4", forRemoval = true)
229234
@Override
235+
@SuppressWarnings("removal")
230236
public final ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
231237
AotContextLoader loader = getAotContextLoader(mergedConfig);
232238
if (logger.isTraceEnabled()) {
@@ -236,6 +242,33 @@ public final ApplicationContext loadContextForAotProcessing(MergedContextConfigu
236242
return loader.loadContextForAotProcessing(mergedConfig);
237243
}
238244

245+
/**
246+
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
247+
* an {@link ApplicationContext} for AOT processing.
248+
* <p>Delegation is based on explicit knowledge of the implementations of the
249+
* default loaders. See {@link #loadContext(MergedContextConfiguration)} for
250+
* details.
251+
* @param mergedConfig the merged context configuration to use to load the application context
252+
* @param runtimeHints the runtime hints
253+
* @return a new application context
254+
* @throws IllegalArgumentException if the supplied merged configuration is {@code null}
255+
* @throws IllegalStateException if neither candidate loader is capable of loading an
256+
* {@code ApplicationContext} from the supplied merged context configuration
257+
* @since 6.2.4
258+
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
259+
*/
260+
@Override
261+
public final ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
262+
RuntimeHints runtimeHints) throws Exception {
263+
264+
AotContextLoader loader = getAotContextLoader(mergedConfig);
265+
if (logger.isTraceEnabled()) {
266+
logger.trace("Delegating to %s to load context for AOT processing for %s"
267+
.formatted(name(loader), mergedConfig));
268+
}
269+
return loader.loadContextForAotProcessing(mergedConfig, runtimeHints);
270+
}
271+
239272
/**
240273
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
241274
* an {@link ApplicationContext} for AOT run-time execution.

spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -21,6 +21,7 @@
2121
import org.apache.commons.logging.Log;
2222
import org.apache.commons.logging.LogFactory;
2323

24+
import org.springframework.aot.hint.RuntimeHints;
2425
import org.springframework.beans.factory.support.BeanDefinitionReader;
2526
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
2627
import org.springframework.context.ApplicationContext;
@@ -126,10 +127,41 @@ public final ApplicationContext loadContext(MergedContextConfiguration mergedCon
126127
* @throws Exception if context loading failed
127128
* @since 6.0
128129
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
130+
* @deprecated as of Spring Framework 6.2.4, in favor of
131+
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
132+
* to be removed in Spring Framework 8.0
129133
*/
134+
@Deprecated(since = "6.2.4", forRemoval = true)
130135
@Override
136+
@SuppressWarnings("removal")
131137
public final GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig)
132138
throws Exception {
139+
140+
return loadContext(mergedConfig, true);
141+
}
142+
143+
/**
144+
* Load a {@link GenericApplicationContext} for AOT build-time processing based
145+
* on the supplied {@link MergedContextConfiguration}.
146+
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
147+
* method does not
148+
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
149+
* refresh} the {@code ApplicationContext} or
150+
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
151+
* register a JVM shutdown hook} for it. Otherwise, this method implements
152+
* behavior identical to {@link #loadContext(MergedContextConfiguration)}.
153+
* @param mergedConfig the merged context configuration to use to load the
154+
* application context
155+
* @param runtimeHints the runtime hints
156+
* @return a new application context
157+
* @throws Exception if context loading failed
158+
* @since 6.2.4
159+
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
160+
*/
161+
@Override
162+
public final GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
163+
RuntimeHints runtimeHints) throws Exception {
164+
133165
return loadContext(mergedConfig, true);
134166
}
135167

spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java

+34-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 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.
@@ -20,6 +20,7 @@
2020
import org.apache.commons.logging.Log;
2121
import org.apache.commons.logging.LogFactory;
2222

23+
import org.springframework.aot.hint.RuntimeHints;
2324
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
2425
import org.springframework.context.ApplicationContext;
2526
import org.springframework.context.ApplicationContextInitializer;
@@ -120,10 +121,41 @@ public final ApplicationContext loadContext(MergedContextConfiguration mergedCon
120121
* @throws Exception if context loading failed
121122
* @since 6.0
122123
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
124+
* @deprecated as of Spring Framework 6.2.4, in favor of
125+
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
126+
* to be removed in Spring Framework 8.0
123127
*/
128+
@Deprecated(since = "6.2.4", forRemoval = true)
124129
@Override
130+
@SuppressWarnings("removal")
125131
public final GenericWebApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig)
126132
throws Exception {
133+
134+
return loadContext(mergedConfig, true);
135+
}
136+
137+
/**
138+
* Load a {@link GenericWebApplicationContext} for AOT build-time processing based
139+
* on the supplied {@link MergedContextConfiguration}.
140+
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
141+
* method does not
142+
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
143+
* refresh} the {@code ApplicationContext} or
144+
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
145+
* register a JVM shutdown hook} for it. Otherwise, this method implements
146+
* behavior identical to {@link #loadContext(MergedContextConfiguration)}.
147+
* @param mergedConfig the merged context configuration to use to load the
148+
* application context
149+
* @param runtimeHints the runtime hints
150+
* @return a new web application context
151+
* @throws Exception if context loading failed
152+
* @since 6.2.4
153+
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
154+
*/
155+
@Override
156+
public final GenericWebApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
157+
RuntimeHints runtimeHints) throws Exception {
158+
127159
return loadContext(mergedConfig, true);
128160
}
129161

@@ -187,7 +219,7 @@ else if (logger.isDebugEnabled()) {
187219
* register a JVM shutdown hook for it
188220
* @return a new web application context
189221
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
190-
* @see org.springframework.test.context.aot.AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
222+
* @see org.springframework.test.context.aot.AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
191223
*/
192224
private GenericWebApplicationContext loadContext(
193225
MergedContextConfiguration mergedConfig, boolean forAotProcessing) throws Exception {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.aot;
18+
19+
import org.springframework.context.ApplicationContextInitializer;
20+
import org.springframework.context.ConfigurableApplicationContext;
21+
import org.springframework.context.support.GenericApplicationContext;
22+
import org.springframework.context.support.StaticApplicationContext;
23+
import org.springframework.test.context.MergedContextConfiguration;
24+
import org.springframework.test.context.support.AbstractContextLoader;
25+
26+
/**
27+
* @author Sam Brannen
28+
* @since 6.2.4
29+
*/
30+
class AbstractAotContextLoader extends AbstractContextLoader implements AotContextLoader {
31+
32+
@Override
33+
public final GenericApplicationContext loadContext(MergedContextConfiguration mergedConfig) {
34+
return new StaticApplicationContext();
35+
}
36+
37+
@Override
38+
public final GenericApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
39+
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) {
40+
41+
return loadContext(mergedConfig);
42+
}
43+
44+
@Override
45+
protected final String getResourceSuffix() {
46+
throw new UnsupportedOperationException();
47+
}
48+
49+
}

0 commit comments

Comments
 (0)