Use empty context for AOT binder child context

Previously, when running in AOT mode the binder child context
was created w/ the same beans as when in JVM mode. The whole
point of the former is to static initialize an empty fresh context
using the AOT generated initializer.
This commit is contained in:
Chris Bono
2022-08-17 00:07:29 -05:00
committed by Artem Bilan
parent 3178464f14
commit 71ee26b0a1
2 changed files with 45 additions and 4 deletions

View File

@@ -153,7 +153,7 @@ public class BinderChildContextInitializer implements ApplicationContextAware, B
this.logger.debug(() -> "Generating AOT child context initializer for " + name);
GenerationContext childGenerationContext = generationContext.withName(name + "Binder");
ClassName initializerClassName = aotGenerator.processAheadOfTime(context, childGenerationContext);
method.addStatement("$T<? extends $T>" + name + "Initializer = new $L()", ApplicationContextInitializer.class,
method.addStatement("$T<? extends $T> " + name + "Initializer = new $L()", ApplicationContextInitializer.class,
ConfigurableApplicationContext.class, initializerClassName);
method.addStatement("initializers.put($S," + name + "Initializer)", name);
});

View File

@@ -265,9 +265,7 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
ConfigurableApplicationContext binderProducingContext;
if (this.binderChildContextInitializers.containsKey(configurationName)) {
this.logger.info("Using AOT pre-prepared initializer to construct binder child context for " + configurationName);
binderProducingContext = this.initializeBinderContextSimple(configurationName, binderProperties,
binderType, binderConfiguration, false);
GenericApplicationContext c = null;
binderProducingContext = this.createUnitializedContextForAOT(configurationName, binderProperties, binderConfiguration);
this.binderChildContextInitializers.get(configurationName).initialize(binderProducingContext);
binderProducingContext.refresh();
}
@@ -447,6 +445,49 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
return binderProducingContext;
}
/**
* Creates a bare minimum application context that can be initialized by AOT.
*
* @param configurationName binder configuration name
* @param binderProperties binder properties
* @param binderConfiguration binder configuration
* @return a binder child application context suitable for AOT initialization
*/
GenericApplicationContext createUnitializedContextForAOT(String configurationName,
Map<String, Object> binderProperties, BinderConfiguration binderConfiguration) {
GenericApplicationContext binderContext = new GenericApplicationContext();
MapPropertySource binderPropertySource = new MapPropertySource(configurationName, binderProperties);
binderContext.getEnvironment().getPropertySources().addFirst(binderPropertySource);
binderContext.setDisplayName(configurationName + "_context");
boolean useApplicationContextAsParent = binderProperties.isEmpty() && this.context != null;
ConfigurableEnvironment environment = this.context != null ? this.context.getEnvironment() : null;
if (useApplicationContextAsParent) {
binderContext.setParent(this.context);
}
else if (this.context != null) {
binderContext.addApplicationListener(event -> {
if (context != null) {
try {
context.publishEvent(event);
}
catch (Exception e) {
logger.warn("Failed to publish " + event, e);
}
}
});
if (environment != null && (useApplicationContextAsParent || binderConfiguration.isInheritEnvironment())) {
binderContext.getEnvironment().merge(environment);
binderContext.getEnvironment().getPropertySources().remove("configurationProperties");
binderContext.getEnvironment().getPropertySources()
.addFirst(new MapPropertySource("defaultBinderFactoryProperties",
Collections.singletonMap("spring.main.web-application-type", "NONE")));
}
}
return binderContext;
}
/**
* Ensures that nested properties are flattened (i.e., foo.bar=baz instead of
* foo={bar=baz}).