diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java index d5e88976b8..2043f08b0d 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.function.Consumer; import org.springframework.beans.BeanUtils; -import org.springframework.boot.AotApplicationContextInitializer; import org.springframework.boot.ApplicationContextFactory; import org.springframework.boot.ConfigurableBootstrapContext; import org.springframework.boot.SpringApplication; @@ -44,6 +43,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.aot.AotApplicationContextInitializer; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.core.SpringVersion; @@ -494,7 +494,7 @@ public class SpringBootContextLoader extends AbstractContextLoader implements Ao ContextLoaderHook.this.configurer.accept(application); if (ContextLoaderHook.this.mode == Mode.AOT_RUNTIME) { application.addInitializers( - AotApplicationContextInitializer.of(ContextLoaderHook.this.initializer)); + (AotApplicationContextInitializer) ContextLoaderHook.this.initializer::initialize); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotApplicationContextInitializer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotApplicationContextInitializer.java deleted file mode 100644 index 716a74fa49..0000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/AotApplicationContextInitializer.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2012-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.boot; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.BeanUtils; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.log.LogMessage; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -/** - * A {@link ApplicationContextInitializer} wrapper used to initialize a - * {@link ConfigurableApplicationContext} using artifacts that were generated - * ahead-of-time. - * - * @param the application context type - * @author Phillip Webb - * @since 3.0.0 - */ -public abstract sealed class AotApplicationContextInitializer - implements ApplicationContextInitializer { - - private static final Log logger = LogFactory.getLog(AotApplicationContextInitializer.class); - - @Override - public final void initialize(C applicationContext) { - logger.debug(LogMessage.format("Initializing ApplicationContext using AOT initializer '%s'", getName())); - aotInitialize(applicationContext); - } - - abstract void aotInitialize(C applicationContext); - - abstract String getName(); - - static AotApplicationContextInitializer forMainApplicationClass( - Class mainApplicationClass) { - String initializerClassName = mainApplicationClass.getName() + "__ApplicationContextInitializer"; - return new ReflectionDelegatingAotApplicationContextInitializer<>(initializerClassName); - } - - /** - * Create a new {@link AotApplicationContextInitializer} by delegating to an existing - * initializer instance. - * @param the application context type - * @param initializer the initializer to delegate to - * @return a new {@link AotApplicationContextInitializer} instance - */ - public static AotApplicationContextInitializer of( - ApplicationContextInitializer initializer) { - Assert.notNull(initializer, "Initializer must not be null"); - return new InstanceDelegatingAotApplicationContextInitializer<>(initializer.getClass().getName(), initializer); - } - - /** - * Create a new {@link AotApplicationContextInitializer} by delegating to an existing - * initializer instance. - * @param the application context type - * @param initializer the initializer to delegate to - * @param name the name of the initializer - * @return a new {@link AotApplicationContextInitializer} instance - */ - public static AotApplicationContextInitializer of(String name, - ApplicationContextInitializer initializer) { - Assert.notNull(name, "Name must not be null"); - Assert.notNull(initializer, "Initializer must not be null"); - return new InstanceDelegatingAotApplicationContextInitializer<>(name, initializer); - } - - /** - * {@link AotApplicationContextInitializer} that delegates to an initializer created - * via reflection. - * - * @param the application context type - */ - static final class ReflectionDelegatingAotApplicationContextInitializer - extends AotApplicationContextInitializer { - - private final String initializerClassName; - - ReflectionDelegatingAotApplicationContextInitializer(String initializerClassName) { - this.initializerClassName = initializerClassName; - } - - @Override - void aotInitialize(C applicationContext) { - ApplicationContextInitializer initializer = createInitializer(applicationContext.getClassLoader()); - initializer.initialize(applicationContext); - } - - @SuppressWarnings("unchecked") - private ApplicationContextInitializer createInitializer(ClassLoader classLoader) { - Class initializerClass = ClassUtils.resolveClassName(this.initializerClassName, classLoader); - Assert.isAssignable(ApplicationContextInitializer.class, initializerClass); - return (ApplicationContextInitializer) BeanUtils.instantiateClass(initializerClass); - } - - @Override - String getName() { - return this.initializerClassName; - } - - } - - /** - * {@link AotApplicationContextInitializer} that delegates to an existing initializer - * instance. - * - * @param the application context type - */ - static final class InstanceDelegatingAotApplicationContextInitializer - extends AotApplicationContextInitializer { - - private final String name; - - private final ApplicationContextInitializer initializer; - - InstanceDelegatingAotApplicationContextInitializer(String name, ApplicationContextInitializer initializer) { - this.name = name; - this.initializer = initializer; - } - - @Override - void aotInitialize(C applicationContext) { - this.initializer.initialize(applicationContext); - } - - @Override - String getName() { - return this.name; - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 569592937e..59d2226e56 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -67,6 +67,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ConfigurationClassPostProcessor; +import org.springframework.context.aot.AotApplicationContextInitializer; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.GenericTypeResolver; @@ -85,7 +86,6 @@ import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; -import org.springframework.core.log.LogMessage; import org.springframework.core.metrics.ApplicationStartup; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -416,19 +416,11 @@ public class SpringApplication { private void addAotGeneratedInitializerIfNecessary(List> initializers) { if (AotDetector.useGeneratedArtifacts()) { - List> aotInitializers = new ArrayList<>(); - for (ApplicationContextInitializer candidate : initializers) { - if (candidate instanceof AotApplicationContextInitializer aotInitializer) { - aotInitializers.add(aotInitializer); - } - } + List> aotInitializers = new ArrayList<>( + initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList()); if (aotInitializers.isEmpty()) { - AotApplicationContextInitializer aotInitializer = AotApplicationContextInitializer - .forMainApplicationClass(this.mainApplicationClass); - aotInitializers.add(aotInitializer); - } - for (AotApplicationContextInitializer aotInitializer : aotInitializers) { - logger.debug(LogMessage.format("Using AOT generated initializer: %s", aotInitializer.getName())); + String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer"; + aotInitializers.add(AotApplicationContextInitializer.forInitializerClasses(initializerClassName)); } initializers.removeAll(aotInitializers); initializers.addAll(0, aotInitializers); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotApplicationContextInitializerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotApplicationContextInitializerTests.java deleted file mode 100644 index 0c01c4a499..0000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/AotApplicationContextInitializerTests.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2012-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.boot; - -import org.junit.jupiter.api.Test; - -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.GenericApplicationContext; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; - -/** - * Tests for {@link AotApplicationContextInitializer}. - * - * @author Phillip Webb - */ -class AotApplicationContextInitializerTests { - - @Test - void forMainApplicationClassUsesReflection() { - AotApplicationContextInitializer initializer = AotApplicationContextInitializer - .forMainApplicationClass(ExampleMain.class); - GenericApplicationContext applicationContext = new GenericApplicationContext(); - initializer.initialize(applicationContext); - assertThat(initializer.getName()).isEqualTo(ExampleMain__ApplicationContextInitializer.class.getName()); - assertThat(applicationContext.getId()).isEqualTo("ExampleMain"); - } - - @Test - void ofWhenInitializerIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> AotApplicationContextInitializer.of(null)) - .withMessage("Initializer must not be null"); - } - - @Test - void ofWithNameWhenInitializerIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> AotApplicationContextInitializer.of("test", null)) - .withMessage("Initializer must not be null"); - } - - @Test - void ofWithNameWhenNameIsNullThrowsException() { - assertThatIllegalArgumentException() - .isThrownBy(() -> AotApplicationContextInitializer.of(null, new CustomApplicationContextInitializer())) - .withMessage("Name must not be null"); - } - - @Test - void ofUsesDelegation() { - AotApplicationContextInitializer initializer = AotApplicationContextInitializer - .of(new CustomApplicationContextInitializer()); - GenericApplicationContext applicationContext = new GenericApplicationContext(); - initializer.initialize(applicationContext); - assertThat(initializer.getName()).isEqualTo(CustomApplicationContextInitializer.class.getName()); - assertThat(applicationContext.getId()).isEqualTo("Custom"); - - } - - static class ExampleMain { - - } - - static class ExampleMain__ApplicationContextInitializer - implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - applicationContext.setId("ExampleMain"); - } - - } - - static class CustomApplicationContextInitializer - implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - applicationContext.setId("Custom"); - } - - } - -}