Skip to content

Commit b286e5a

Browse files
committed
Prevent ServletComponentScan to run again with AOT
Closes gh-34563
1 parent 8a43710 commit b286e5a

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrar.java

+11
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
import java.util.Set;
2323
import java.util.function.Supplier;
2424

25+
import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
2526
import org.springframework.beans.factory.config.BeanDefinition;
2627
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2728
import org.springframework.beans.factory.support.GenericBeanDefinition;
29+
import org.springframework.beans.factory.support.RegisteredBean;
2830
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
2931
import org.springframework.core.annotation.AnnotationAttributes;
3032
import org.springframework.core.type.AnnotationMetadata;
@@ -100,4 +102,13 @@ private void addPackageNames(Collection<String> additionalPackageNames) {
100102

101103
}
102104

105+
static class ServletComponentScanBeanRegistrationExcludeFilter implements BeanRegistrationExcludeFilter {
106+
107+
@Override
108+
public boolean isExcludedFromAotProcessing(RegisteredBean registeredBean) {
109+
return BEAN_NAME.equals(registeredBean.getBeanName());
110+
}
111+
112+
}
113+
103114
}

spring-boot-project/spring-boot/src/main/resources/META-INF/spring/aot.factories

+3
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ org.springframework.boot.jackson.JsonComponentModule.JsonComponentBeanFactoryIni
2020
org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\
2121
org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrationAotProcessor,\
2222
org.springframework.boot.jackson.JsonMixinModuleEntriesBeanRegistrationAotProcessor
23+
24+
org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\
25+
org.springframework.boot.web.servlet.ServletComponentScanRegistrar.ServletComponentScanBeanRegistrationExcludeFilter

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java

+35
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,22 @@
1616

1717
package org.springframework.boot.web.servlet;
1818

19+
import java.util.function.Consumer;
20+
1921
import org.junit.jupiter.api.AfterEach;
2022
import org.junit.jupiter.api.Test;
2123

24+
import org.springframework.aot.test.generate.TestGenerationContext;
2225
import org.springframework.beans.factory.support.RootBeanDefinition;
26+
import org.springframework.context.ApplicationContextInitializer;
2327
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2428
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.context.aot.ApplicationContextAotGenerator;
30+
import org.springframework.context.support.GenericApplicationContext;
2531
import org.springframework.core.annotation.AnnotationConfigurationException;
32+
import org.springframework.core.test.tools.CompileWithForkedClassLoader;
33+
import org.springframework.core.test.tools.TestCompiler;
34+
import org.springframework.javapoet.ClassName;
2635

2736
import static org.assertj.core.api.Assertions.assertThat;
2837
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -121,6 +130,32 @@ void basePackageAndNoBasePackageAreCombinedCorrectly() {
121130
"com.example.foo", "com.example.bar");
122131
}
123132

133+
@Test
134+
@CompileWithForkedClassLoader
135+
void processAheadOfTimeDoesNotRegisterServletComponentRegisteringPostProcessor() {
136+
GenericApplicationContext context = new AnnotationConfigApplicationContext();
137+
context.registerBean(BasePackages.class);
138+
compile(context, (freshContext) -> {
139+
freshContext.refresh();
140+
assertThat(freshContext.getBeansOfType(ServletComponentRegisteringPostProcessor.class)).isEmpty();
141+
});
142+
}
143+
144+
@SuppressWarnings("unchecked")
145+
private void compile(GenericApplicationContext context, Consumer<GenericApplicationContext> freshContext) {
146+
TestGenerationContext generationContext = new TestGenerationContext(
147+
ClassName.get(getClass().getPackageName(), "TestTarget"));
148+
ClassName className = new ApplicationContextAotGenerator().processAheadOfTime(context, generationContext);
149+
generationContext.writeGeneratedContent();
150+
TestCompiler.forSystem().with(generationContext).compile((compiled) -> {
151+
GenericApplicationContext freshApplicationContext = new GenericApplicationContext();
152+
ApplicationContextInitializer<GenericApplicationContext> initializer = compiled
153+
.getInstance(ApplicationContextInitializer.class, className.toString());
154+
initializer.initialize(freshApplicationContext);
155+
freshContext.accept(freshApplicationContext);
156+
});
157+
}
158+
124159
@Configuration(proxyBeanMethods = false)
125160
@ServletComponentScan({ "com.example.foo", "com.example.bar" })
126161
static class ValuePackages {

0 commit comments

Comments
 (0)