Adapt to latest API change in Spring Framework

See https://github.com/spring-projects/spring-framework/issues/28585
pull/31520/head
Stephane Nicoll 2 years ago
parent 114b896e3c
commit fe39598e81

@ -30,7 +30,6 @@ import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter; import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.boot.AotProcessor;
import org.springframework.boot.LazyInitializationBeanFactoryPostProcessor; import org.springframework.boot.LazyInitializationBeanFactoryPostProcessor;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory; import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
@ -96,10 +95,9 @@ class ChildManagementContextInitializer implements ApplicationListener<WebServer
BeanFactory parentBeanFactory = ((ConfigurableApplicationContext) this.parentContext).getBeanFactory(); BeanFactory parentBeanFactory = ((ConfigurableApplicationContext) this.parentContext).getBeanFactory();
if (registeredBean.getBeanClass().equals(getClass()) if (registeredBean.getBeanClass().equals(getClass())
&& registeredBean.getBeanFactory().equals(parentBeanFactory)) { && registeredBean.getBeanFactory().equals(parentBeanFactory)) {
AotProcessor activeAotProcessor = AotProcessor.getActive(this.parentContext);
ConfigurableApplicationContext managementContext = createManagementContext(); ConfigurableApplicationContext managementContext = createManagementContext();
registerBeans(managementContext); registerBeans(managementContext);
return new AotContribution(activeAotProcessor, managementContext); return new AotContribution(managementContext);
} }
return null; return null;
} }
@ -155,23 +153,18 @@ class ChildManagementContextInitializer implements ApplicationListener<WebServer
*/ */
private static class AotContribution implements BeanRegistrationAotContribution { private static class AotContribution implements BeanRegistrationAotContribution {
private final AotProcessor activeAotProcessor;
private final GenericApplicationContext managementContext; private final GenericApplicationContext managementContext;
AotContribution(AotProcessor activeAotProcessor, ConfigurableApplicationContext managementContext) { AotContribution(ConfigurableApplicationContext managementContext) {
Assert.isInstanceOf(GenericApplicationContext.class, managementContext); Assert.isInstanceOf(GenericApplicationContext.class, managementContext);
this.activeAotProcessor = activeAotProcessor;
this.managementContext = (GenericApplicationContext) managementContext; this.managementContext = (GenericApplicationContext) managementContext;
} }
@Override @Override
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
Class<?> target = (this.activeAotProcessor != null) ? this.activeAotProcessor.getApplication() : null; GenerationContext managementGenerationContext = generationContext.withName("Management");
ClassName generatedInitializerClassName = generationContext.getClassNameGenerator() ClassName generatedInitializerClassName = new ApplicationContextAotGenerator()
.generateClassName(target, "ManagementContextRegistrations"); .generateApplicationContext(this.managementContext, managementGenerationContext);
new ApplicationContextAotGenerator().generateApplicationContext(this.managementContext, target,
"Management", generationContext, generatedInitializerClassName);
GeneratedMethod postProcessorMethod = beanRegistrationCode.getMethodGenerator() GeneratedMethod postProcessorMethod = beanRegistrationCode.getMethodGenerator()
.generateMethod("addManagementInitializer").using((builder) -> { .generateMethod("addManagementInitializer").using((builder) -> {
builder.addJavadoc("Use AOT management context initialization"); builder.addJavadoc("Use AOT management context initialization");

@ -25,13 +25,11 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.aot.generate.ClassNameGenerator;
import org.springframework.aot.generate.DefaultGenerationContext; import org.springframework.aot.generate.DefaultGenerationContext;
import org.springframework.aot.generate.InMemoryGeneratedFiles; import org.springframework.aot.generate.InMemoryGeneratedFiles;
import org.springframework.aot.generate.MethodGenerator;
import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.test.generator.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generator.compile.CompileWithTargetClassAccess;
import org.springframework.aot.test.generator.compile.TestCompiler; import org.springframework.aot.test.generator.compile.TestCompiler;
import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
@ -79,10 +77,10 @@ class ChildManagementContextInitializerAotTests {
EndpointAutoConfiguration.class)); EndpointAutoConfiguration.class));
contextRunner.withPropertyValues("server.port=0", "management.server.port=0").prepare((context) -> { contextRunner.withPropertyValues("server.port=0", "management.server.port=0").prepare((context) -> {
InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles(); InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
DefaultGenerationContext generationContext = new DefaultGenerationContext(generatedFiles); DefaultGenerationContext generationContext = new DefaultGenerationContext(
ClassName className = ClassName.get("com.example", "TestInitializer"); new ClassNameGenerator(TestTarget.class), generatedFiles);
new ApplicationContextAotGenerator().generateApplicationContext( ClassName className = new ApplicationContextAotGenerator().generateApplicationContext(
(GenericApplicationContext) context.getSourceApplicationContext(), generationContext, className); (GenericApplicationContext) context.getSourceApplicationContext(), generationContext);
generationContext.writeGeneratedContent(); generationContext.writeGeneratedContent();
TestCompiler compiler = TestCompiler.forSystem(); TestCompiler compiler = TestCompiler.forSystem();
compiler.withFiles(generatedFiles).compile((compiled) -> { compiler.withFiles(generatedFiles).compile((compiled) -> {
@ -105,21 +103,7 @@ class ChildManagementContextInitializerAotTests {
}; };
} }
static class MockBeanRegistrationCode implements BeanRegistrationCode { static class TestTarget {
@Override
public ClassName getClassName() {
return null;
}
@Override
public MethodGenerator getMethodGenerator() {
return null;
}
@Override
public void addInstancePostProcessor(MethodReference methodReference) {
}
} }

@ -25,10 +25,9 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.springframework.aot.generate.ClassNameGenerator;
import org.springframework.aot.generate.DefaultGenerationContext; import org.springframework.aot.generate.DefaultGenerationContext;
import org.springframework.aot.generate.FileSystemGeneratedFiles; import org.springframework.aot.generate.FileSystemGeneratedFiles;
import org.springframework.aot.generate.GeneratedFiles.Kind; import org.springframework.aot.generate.GeneratedFiles.Kind;
@ -62,8 +61,6 @@ public class AotProcessor {
private static final Consumer<ExecutableHint.Builder> INVOKE_CONSTRUCTOR_HINT = (hint) -> hint private static final Consumer<ExecutableHint.Builder> INVOKE_CONSTRUCTOR_HINT = (hint) -> hint
.setModes(ExecutableMode.INVOKE); .setModes(ExecutableMode.INVOKE);
private static final Map<ApplicationContext, AotProcessor> aotProcessors = new ConcurrentHashMap<>();
private final Class<?> application; private final Class<?> application;
private final String[] applicationArgs; private final String[] applicationArgs;
@ -101,32 +98,18 @@ public class AotProcessor {
this.artifactId = artifactId; this.artifactId = artifactId;
} }
/**
* Return the application class being processed.
* @return the application class
*/
public Class<?> getApplication() {
return this.application;
}
/** /**
* Trigger the processing of the application managed by this instance. * Trigger the processing of the application managed by this instance.
*/ */
void process() { public void process() {
deleteExistingOutput(); deleteExistingOutput();
AotProcessorHook hook = new AotProcessorHook(); AotProcessorHook hook = new AotProcessorHook();
SpringApplicationHooks.withHook(hook, this::callApplicationMainMethod); SpringApplicationHooks.withHook(hook, this::callApplicationMainMethod);
GenericApplicationContext applicationContext = hook.getApplicationContext(); GenericApplicationContext applicationContext = hook.getApplicationContext();
Assert.notNull(applicationContext, "No application context available after calling main method of '" Assert.notNull(applicationContext, "No application context available after calling main method of '"
+ this.application.getName() + "'. Does it run a SpringApplication?"); + this.application.getName() + "'. Does it run a SpringApplication?");
aotProcessors.put(applicationContext, this);
try {
performAotProcessing(applicationContext); performAotProcessing(applicationContext);
} }
finally {
aotProcessors.remove(applicationContext);
}
}
private void deleteExistingOutput() { private void deleteExistingOutput() {
deleteExistingOutput(this.sourceOutput, this.resourceOutput, this.classOutput); deleteExistingOutput(this.sourceOutput, this.resourceOutput, this.classOutput);
@ -161,12 +144,11 @@ public class AotProcessor {
private void performAotProcessing(GenericApplicationContext applicationContext) { private void performAotProcessing(GenericApplicationContext applicationContext) {
FileSystemGeneratedFiles generatedFiles = new FileSystemGeneratedFiles(this::getRoot); FileSystemGeneratedFiles generatedFiles = new FileSystemGeneratedFiles(this::getRoot);
DefaultGenerationContext generationContext = new DefaultGenerationContext(generatedFiles); DefaultGenerationContext generationContext = new DefaultGenerationContext(
new ClassNameGenerator(this.application), generatedFiles);
ApplicationContextAotGenerator generator = new ApplicationContextAotGenerator(); ApplicationContextAotGenerator generator = new ApplicationContextAotGenerator();
ClassName generatedInitializerClassName = generationContext.getClassNameGenerator() ClassName generatedInitializerClassName = generator.generateApplicationContext(applicationContext,
.generateClassName(this.application, "ApplicationContextInitializer"); generationContext);
generator.generateApplicationContext(applicationContext, this.application, "", generationContext,
generatedInitializerClassName);
registerEntryPointHint(generationContext, generatedInitializerClassName); registerEntryPointHint(generationContext, generatedInitializerClassName);
generationContext.writeGeneratedContent(); generationContext.writeGeneratedContent();
writeHints(generationContext.getRuntimeHints()); writeHints(generationContext.getRuntimeHints());
@ -243,16 +225,6 @@ public class AotProcessor {
.process(); .process();
} }
/**
* Return the AOT processor that is actively processing the given
* {@link ApplicationContext}.
* @param applicationContext the application context to check
* @return the {@link AotProcessor} or {@code null}
*/
public static AotProcessor getActive(ApplicationContext applicationContext) {
return aotProcessors.get(applicationContext);
}
/** /**
* Hook used to capture the {@link ApplicationContext} and trigger early exit of main * Hook used to capture the {@link ApplicationContext} and trigger early exit of main
* method. * method.

@ -25,6 +25,7 @@ import java.util.function.Consumer;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.aot.generate.ClassNameGenerator;
import org.springframework.aot.generate.DefaultGenerationContext; import org.springframework.aot.generate.DefaultGenerationContext;
import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.generate.InMemoryGeneratedFiles; import org.springframework.aot.generate.InMemoryGeneratedFiles;
@ -267,7 +268,8 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
private RuntimeHints process(ConfigurableListableBeanFactory beanFactory) { private RuntimeHints process(ConfigurableListableBeanFactory beanFactory) {
BeanFactoryInitializationAotContribution contribution = this.processor.processAheadOfTime(beanFactory); BeanFactoryInitializationAotContribution contribution = this.processor.processAheadOfTime(beanFactory);
assertThat(contribution).isNotNull(); assertThat(contribution).isNotNull();
GenerationContext generationContext = new DefaultGenerationContext(new InMemoryGeneratedFiles()); GenerationContext generationContext = new DefaultGenerationContext(new ClassNameGenerator(Object.class),
new InMemoryGeneratedFiles());
contribution.applyTo(generationContext, mock(BeanFactoryInitializationCode.class)); contribution.applyTo(generationContext, mock(BeanFactoryInitializationCode.class));
return generationContext.getRuntimeHints(); return generationContext.getRuntimeHints();
} }

Loading…
Cancel
Save