2323import java .util .List ;
2424import java .util .function .Consumer ;
2525
26+ import org .jspecify .annotations .Nullable ;
27+
2628import org .springframework .aot .hint .ExecutableMode ;
2729import org .springframework .aot .hint .RuntimeHints ;
2830import org .springframework .beans .BeanUtils ;
@@ -105,6 +107,8 @@ public class SpringBootContextLoader extends AbstractContextLoader implements Ao
105107 private static final Consumer <SpringApplication > ALREADY_CONFIGURED = (springApplication ) -> {
106108 };
107109
110+ private static final Object NONE = new Object ();
111+
108112 @ Override
109113 public ApplicationContext loadContext (MergedContextConfiguration mergedConfig ) throws Exception {
110114 return loadContext (mergedConfig , Mode .STANDARD , null , null );
@@ -123,8 +127,8 @@ public ApplicationContext loadContextForAotRuntime(MergedContextConfiguration me
123127 }
124128
125129 private ApplicationContext loadContext (MergedContextConfiguration mergedConfig , Mode mode ,
126- ApplicationContextInitializer <ConfigurableApplicationContext > initializer , RuntimeHints runtimeHints )
127- throws Exception {
130+ @ Nullable ApplicationContextInitializer <ConfigurableApplicationContext > initializer ,
131+ @ Nullable RuntimeHints runtimeHints ) throws Exception {
128132 assertHasClassesOrLocations (mergedConfig );
129133 SpringBootTestAnnotation annotation = SpringBootTestAnnotation .get (mergedConfig );
130134 String [] args = annotation .getArgs ();
@@ -153,7 +157,7 @@ private void assertHasClassesOrLocations(MergedContextConfiguration mergedConfig
153157 + SpringVersion .getVersion () + ")." );
154158 }
155159
156- private Method getMainMethod (MergedContextConfiguration mergedConfig , UseMainMethod useMainMethod ) {
160+ private @ Nullable Method getMainMethod (MergedContextConfiguration mergedConfig , UseMainMethod useMainMethod ) {
157161 if (useMainMethod == UseMainMethod .NEVER ) {
158162 return null ;
159163 }
@@ -167,14 +171,16 @@ private Method getMainMethod(MergedContextConfiguration mergedConfig, UseMainMet
167171 "Cannot use main method as no @SpringBootConfiguration-annotated class is available" );
168172 Method mainMethod = findMainMethod (springBootConfiguration );
169173 Assert .state (mainMethod != null || useMainMethod == UseMainMethod .WHEN_AVAILABLE ,
170- () -> "Main method not found on '%s'" .formatted (springBootConfiguration .getName ()));
174+ () -> "Main method not found on '%s'"
175+ .formatted ((springBootConfiguration != null ) ? springBootConfiguration .getName () : null ));
171176 return mainMethod ;
172177 }
173178
174- private static Method findMainMethod (Class <?> type ) {
179+ private static @ Nullable Method findMainMethod (@ Nullable Class <?> type ) {
175180 Method mainMethod = (type != null ) ? ReflectionUtils .findMethod (type , "main" , String [].class ) : null ;
176181 if (mainMethod == null && KotlinDetector .isKotlinPresent ()) {
177182 try {
183+ Assert .state (type != null , "'type' must not be null" );
178184 Class <?> kotlinClass = ClassUtils .forName (type .getName () + "Kt" , type .getClassLoader ());
179185 mainMethod = ReflectionUtils .findMethod (kotlinClass , "main" , String [].class );
180186 }
@@ -285,7 +291,7 @@ protected SpringApplication getSpringApplication() {
285291 * method if you need a custom environment.
286292 * @return a {@link ConfigurableEnvironment} instance
287293 */
288- protected ConfigurableEnvironment getEnvironment () {
294+ protected @ Nullable ConfigurableEnvironment getEnvironment () {
289295 return null ;
290296 }
291297
@@ -462,9 +468,9 @@ public void initialize(ConfigurableApplicationContext applicationContext) {
462468 private static class ParentContextApplicationContextInitializer
463469 implements ApplicationContextInitializer <ConfigurableApplicationContext > {
464470
465- private final ApplicationContext parent ;
471+ private final @ Nullable ApplicationContext parent ;
466472
467- ParentContextApplicationContextInitializer (ApplicationContext parent ) {
473+ ParentContextApplicationContextInitializer (@ Nullable ApplicationContext parent ) {
468474 this .parent = parent ;
469475 }
470476
@@ -507,15 +513,16 @@ private static class ContextLoaderHook implements SpringApplicationHook {
507513
508514 private final Mode mode ;
509515
510- private final ApplicationContextInitializer <ConfigurableApplicationContext > initializer ;
516+ private final @ Nullable ApplicationContextInitializer <ConfigurableApplicationContext > initializer ;
511517
512518 private final Consumer <SpringApplication > configurer ;
513519
514520 private final List <ApplicationContext > contexts = Collections .synchronizedList (new ArrayList <>());
515521
516522 private final List <ApplicationContext > failedContexts = Collections .synchronizedList (new ArrayList <>());
517523
518- ContextLoaderHook (Mode mode , ApplicationContextInitializer <ConfigurableApplicationContext > initializer ,
524+ ContextLoaderHook (Mode mode ,
525+ @ Nullable ApplicationContextInitializer <ConfigurableApplicationContext > initializer ,
519526 Consumer <SpringApplication > configurer ) {
520527 this .mode = mode ;
521528 this .initializer = initializer ;
@@ -530,6 +537,7 @@ public SpringApplicationRunListener getRunListener(SpringApplication application
530537 public void starting (ConfigurableBootstrapContext bootstrapContext ) {
531538 ContextLoaderHook .this .configurer .accept (application );
532539 if (ContextLoaderHook .this .mode == Mode .AOT_RUNTIME ) {
540+ Assert .state (ContextLoaderHook .this .initializer != null , "'initializer' must not be null" );
533541 application .addInitializers (
534542 (AotApplicationContextInitializer <?>) ContextLoaderHook .this .initializer ::initialize );
535543 }
@@ -544,24 +552,24 @@ public void contextLoaded(ConfigurableApplicationContext context) {
544552 }
545553
546554 @ Override
547- public void failed (ConfigurableApplicationContext context , Throwable exception ) {
555+ public void failed (@ Nullable ConfigurableApplicationContext context , Throwable exception ) {
548556 ContextLoaderHook .this .failedContexts .add (context );
549557 }
550558
551559 };
552560 }
553561
554- private < T > ApplicationContext runMain (Runnable action ) throws Exception {
562+ private ApplicationContext runMain (Runnable action ) throws Exception {
555563 return run (() -> {
556564 action .run ();
557- return null ;
565+ return NONE ;
558566 });
559567 }
560568
561- private ApplicationContext run (ThrowingSupplier <ConfigurableApplicationContext > action ) throws Exception {
569+ private ApplicationContext run (ThrowingSupplier <? > action ) throws Exception {
562570 try {
563- ConfigurableApplicationContext context = SpringApplication .withHook (this , action );
564- if (context != null ) {
571+ Object result = SpringApplication .withHook (this , action );
572+ if (result instanceof ApplicationContext context ) {
565573 return context ;
566574 }
567575 }
0 commit comments