diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrar.java index 49d548f16b5..188e8a9b656 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrar.java @@ -22,9 +22,11 @@ import java.util.LinkedHashSet; import java.util.Set; import java.util.function.Supplier; +import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; @@ -100,4 +102,13 @@ class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar { } + static class ServletComponentScanBeanRegistrationExcludeFilter implements BeanRegistrationExcludeFilter { + + @Override + public boolean isExcludedFromAotProcessing(RegisteredBean registeredBean) { + return BEAN_NAME.equals(registeredBean.getBeanName()); + } + + } + } diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories index 905cd717406..7996bc7918e 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories @@ -20,3 +20,6 @@ org.springframework.boot.jackson.JsonComponentModule.JsonComponentBeanFactoryIni org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrationAotProcessor,\ org.springframework.boot.jackson.JsonMixinModuleEntriesBeanRegistrationAotProcessor + +org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\ +org.springframework.boot.web.servlet.ServletComponentScanRegistrar.ServletComponentScanBeanRegistrationExcludeFilter \ No newline at end of file diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java index 8f3b41b0ac2..ff784ba9b85 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java @@ -16,13 +16,22 @@ package org.springframework.boot.web.servlet; +import java.util.function.Consumer; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.context.aot.ApplicationContextAotGenerator; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.annotation.AnnotationConfigurationException; +import org.springframework.core.test.tools.CompileWithForkedClassLoader; +import org.springframework.core.test.tools.TestCompiler; +import org.springframework.javapoet.ClassName; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -121,6 +130,32 @@ class ServletComponentScanRegistrarTests { "com.example.foo", "com.example.bar"); } + @Test + @CompileWithForkedClassLoader + void processAheadOfTimeDoesNotRegisterServletComponentRegisteringPostProcessor() { + GenericApplicationContext context = new AnnotationConfigApplicationContext(); + context.registerBean(BasePackages.class); + compile(context, (freshContext) -> { + freshContext.refresh(); + assertThat(freshContext.getBeansOfType(ServletComponentRegisteringPostProcessor.class)).isEmpty(); + }); + } + + @SuppressWarnings("unchecked") + private void compile(GenericApplicationContext context, Consumer freshContext) { + TestGenerationContext generationContext = new TestGenerationContext( + ClassName.get(getClass().getPackageName(), "TestTarget")); + ClassName className = new ApplicationContextAotGenerator().processAheadOfTime(context, generationContext); + generationContext.writeGeneratedContent(); + TestCompiler.forSystem().with(generationContext).compile((compiled) -> { + GenericApplicationContext freshApplicationContext = new GenericApplicationContext(); + ApplicationContextInitializer initializer = compiled + .getInstance(ApplicationContextInitializer.class, className.toString()); + initializer.initialize(freshApplicationContext); + freshContext.accept(freshApplicationContext); + }); + } + @Configuration(proxyBeanMethods = false) @ServletComponentScan({ "com.example.foo", "com.example.bar" }) static class ValuePackages {