Permit AOT-generated code to run on the JVM as well

This commit updates the codebase so that AOT-generated code can run on
the JVM in an opt-in fashion alongside the existing support of native
images.

When optimizations have been generated, setting the "spring.aot.enabled"
spring property (JVM or spring.properties) allows to opt-in for that
behavior on the JVM.

Closes gh-31244
pull/31267/head
Stephane Nicoll 2 years ago
parent 0dbcb5f6d3
commit fb439b6824

@ -18,11 +18,11 @@ package org.springframework.boot;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.springframework.aot.AotDetector;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.NativeDetector;
import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.core.io.support.SpringFactoriesLoader;
/** /**
@ -51,7 +51,7 @@ public interface ApplicationContextFactory {
return context; return context;
} }
} }
return NativeDetector.inNativeImage() ? new GenericApplicationContext() return AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext()
: new AnnotationConfigApplicationContext(); : new AnnotationConfigApplicationContext();
} }
catch (Exception ex) { catch (Exception ex) {

@ -32,6 +32,7 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.aot.AotDetector;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.CachedIntrospectionResults; import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
@ -59,10 +60,10 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.aot.ApplicationContextAotInitializer;
import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
import org.springframework.core.NativeDetector;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
@ -401,7 +402,7 @@ public class SpringApplication {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
} }
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context)); context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
if (!NativeDetector.inNativeImage()) { if (!AotDetector.useGeneratedArtifacts()) {
// Load the sources // Load the sources
Set<Object> sources = getAllSources(); Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty"); Assert.notEmpty(sources, "Sources must not be empty");
@ -411,18 +412,13 @@ public class SpringApplication {
} }
private void addAotGeneratedInitializerIfNecessary(List<ApplicationContextInitializer<?>> initializers) { private void addAotGeneratedInitializerIfNecessary(List<ApplicationContextInitializer<?>> initializers) {
if (NativeDetector.inNativeImage()) { if (AotDetector.useGeneratedArtifacts()) {
try { String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
Class<?> initializerClass = Class.forName( if (logger.isDebugEnabled()) {
this.mainApplicationClass.getName() + "__ApplicationContextInitializer", true, logger.debug("Using AOT generated initializer: " + initializerClassName);
getClassLoader());
ApplicationContextInitializer<?> initializer = (ApplicationContextInitializer<?>) initializerClass
.getDeclaredConstructor().newInstance();
initializers.add(0, initializer);
}
catch (Exception ex) {
throw new IllegalArgumentException("Failed to load AOT-generated ApplicationContextInitializer", ex);
} }
initializers.add(0,
(context) -> new ApplicationContextAotInitializer().initialize(context, initializerClassName));
} }
} }

@ -16,10 +16,10 @@
package org.springframework.boot.web.reactive.context; package org.springframework.boot.web.reactive.context;
import org.springframework.aot.AotDetector;
import org.springframework.boot.ApplicationContextFactory; import org.springframework.boot.ApplicationContextFactory;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.WebApplicationType;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.NativeDetector;
/** /**
* {@link ApplicationContextFactory} registered in {@code spring.factories} to support * {@link ApplicationContextFactory} registered in {@code spring.factories} to support
@ -36,7 +36,7 @@ class ReactiveWebServerApplicationContextFactory implements ApplicationContextFa
if (webApplicationType != WebApplicationType.REACTIVE) { if (webApplicationType != WebApplicationType.REACTIVE) {
return null; return null;
} }
return NativeDetector.inNativeImage() ? new ReactiveWebServerApplicationContext() return AotDetector.useGeneratedArtifacts() ? new ReactiveWebServerApplicationContext()
: new AnnotationConfigReactiveWebServerApplicationContext(); : new AnnotationConfigReactiveWebServerApplicationContext();
} }

@ -16,10 +16,10 @@
package org.springframework.boot.web.servlet.context; package org.springframework.boot.web.servlet.context;
import org.springframework.aot.AotDetector;
import org.springframework.boot.ApplicationContextFactory; import org.springframework.boot.ApplicationContextFactory;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.WebApplicationType;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.NativeDetector;
/** /**
* {@link ApplicationContextFactory} registered in {@code spring.factories} to support * {@link ApplicationContextFactory} registered in {@code spring.factories} to support
@ -36,7 +36,7 @@ class ServletWebServerApplicationContextFactory implements ApplicationContextFac
if (webApplicationType != WebApplicationType.SERVLET) { if (webApplicationType != WebApplicationType.SERVLET) {
return null; return null;
} }
return NativeDetector.inNativeImage() ? new ServletWebServerApplicationContext() return AotDetector.useGeneratedArtifacts() ? new ServletWebServerApplicationContext()
: new AnnotationConfigServletWebServerApplicationContext(); : new AnnotationConfigServletWebServerApplicationContext();
} }

Loading…
Cancel
Save