Skip to content

Commit ce7a5a5

Browse files
committed
WIP support for modular Spring AOT
This commit which leverages https://github.com/sdeleuze/spring-framework/tree/modular-spring-aot introduces support for modular Spring AOT, with the main goal to provide more control on which benefits/side effects are enabled. It introduces 4 new boolean properties to the Gradle AOT tasks: - beanRegistration - predefinedClasses - classpathIndexes - reachabilityMetadata When none of those 4 boolean properties are defined, they are all enabled to keep backward compatibility. Build configuration example: processAot { predefinedClasses = true classpathIndexes = true } Other possible options for DevXP: - Some artifact types enabled by default on the JVM when Spring AOT processing happen but -Dspring.aot.enabled is not specified - Have some kind of "JVM mode" flag
1 parent bd1df38 commit ce7a5a5

File tree

4 files changed

+76
-7
lines changed

4 files changed

+76
-7
lines changed

build-plugin/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/aot/AbstractAot.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,27 @@
1717
package org.springframework.boot.gradle.tasks.aot;
1818

1919
import java.util.ArrayList;
20+
import java.util.HashSet;
2021
import java.util.List;
22+
import java.util.Set;
23+
import java.util.stream.Collectors;
2124

2225
import org.gradle.api.file.DirectoryProperty;
2326
import org.gradle.api.provider.Property;
2427
import org.gradle.api.tasks.Input;
2528
import org.gradle.api.tasks.JavaExec;
29+
import org.gradle.api.tasks.Optional;
2630
import org.gradle.api.tasks.OutputDirectory;
2731
import org.gradle.work.DisableCachingByDefault;
2832

33+
import org.springframework.aot.generate.GeneratedArtifact;
34+
2935
/**
3036
* Specialization of {@link JavaExec} to be used as a base class for tasks that perform
3137
* ahead-of-time processing.
3238
*
3339
* @author Andy Wilkinson
40+
* @author Sebastien Deleuze
3441
* @since 3.0.0
3542
*/
3643
@DisableCachingByDefault(because = "Cacheability can only be determined by a concrete implementation")
@@ -46,12 +53,24 @@ public abstract class AbstractAot extends JavaExec {
4653

4754
private final Property<String> artifactId;
4855

56+
private final Property<Boolean> beanRegistration;
57+
58+
private final Property<Boolean> predefinedClasses;
59+
60+
private final Property<Boolean> classpathIndexes;
61+
62+
private final Property<Boolean> reachabilityMetadata;
63+
4964
protected AbstractAot() {
5065
this.sourcesDir = getProject().getObjects().directoryProperty();
5166
this.resourcesDir = getProject().getObjects().directoryProperty();
5267
this.classesDir = getProject().getObjects().directoryProperty();
5368
this.groupId = getProject().getObjects().property(String.class);
5469
this.artifactId = getProject().getObjects().property(String.class);
70+
this.beanRegistration = getProject().getObjects().property(Boolean.class);
71+
this.predefinedClasses = getProject().getObjects().property(Boolean.class);
72+
this.classpathIndexes = getProject().getObjects().property(Boolean.class);
73+
this.reachabilityMetadata = getProject().getObjects().property(Boolean.class);
5574
}
5675

5776
/**
@@ -99,13 +118,57 @@ public final DirectoryProperty getClassesOutput() {
99118
return this.classesDir;
100119
}
101120

121+
@Input
122+
@Optional
123+
public final Property<Boolean> getBeanRegistration() {
124+
return this.beanRegistration;
125+
}
126+
127+
@Input
128+
@Optional
129+
public final Property<Boolean> getPredefinedClasses() {
130+
return this.predefinedClasses;
131+
}
132+
133+
@Input
134+
@Optional
135+
public final Property<Boolean> getClasspathIndexes() {
136+
return this.classpathIndexes;
137+
}
138+
139+
@Input
140+
@Optional
141+
public final Property<Boolean> getReachabilityMetadata() {
142+
return this.reachabilityMetadata;
143+
}
144+
102145
List<String> processorArgs() {
103146
List<String> args = new ArrayList<>();
104147
args.add(getSourcesOutput().getAsFile().get().getAbsolutePath());
105148
args.add(getResourcesOutput().getAsFile().get().getAbsolutePath());
106149
args.add(getClassesOutput().getAsFile().get().getAbsolutePath());
107150
args.add(getGroupId().get());
108151
args.add(getArtifactId().get());
152+
Set<GeneratedArtifact> artifactTypes = new HashSet<>();
153+
if (Boolean.TRUE.equals(this.beanRegistration.getOrNull())) {
154+
artifactTypes.add(GeneratedArtifact.BEAN_REGISTRATION);
155+
}
156+
if (Boolean.TRUE.equals(this.predefinedClasses.getOrNull())) {
157+
artifactTypes.add(GeneratedArtifact.PREDEFINED_CLASSES);
158+
}
159+
if (Boolean.TRUE.equals(this.classpathIndexes.getOrNull())) {
160+
artifactTypes.add(GeneratedArtifact.CLASSPATH_INDEXES);
161+
}
162+
if (Boolean.TRUE.equals(this.reachabilityMetadata.getOrNull())) {
163+
artifactTypes.add(GeneratedArtifact.REACHABILITY_METADATA);
164+
}
165+
if (artifactTypes.isEmpty()) {
166+
artifactTypes.add(GeneratedArtifact.BEAN_REGISTRATION);
167+
artifactTypes.add(GeneratedArtifact.PREDEFINED_CLASSES);
168+
artifactTypes.add(GeneratedArtifact.CLASSPATH_INDEXES);
169+
artifactTypes.add(GeneratedArtifact.REACHABILITY_METADATA);
170+
}
171+
args.add(artifactTypes.stream().map(GeneratedArtifact::toString).collect(Collectors.joining(",")));
109172
args.addAll(super.getArgs());
110173
return args;
111174
}

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ subprojects {
3939
includeGroup "net.shibboleth"
4040
}
4141
}
42+
mavenLocal()
4243
spring.mavenRepositories()
4344
}
4445

core/spring-boot/src/main/java/org/springframework/boot/SpringApplicationAotProcessor.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.nio.file.Paths;
2121
import java.util.Arrays;
2222

23+
import org.springframework.aot.generate.GeneratedArtifact;
2324
import org.springframework.boot.SpringApplication.AbandonedRunException;
2425
import org.springframework.context.ApplicationContext;
2526
import org.springframework.context.ConfigurableApplicationContext;
@@ -38,6 +39,7 @@
3839
* @author Stephane Nicoll
3940
* @author Andy Wilkinson
4041
* @author Phillip Webb
42+
* @author Sebastien Deleuze
4143
* @since 3.0.0
4244
*/
4345
public class SpringApplicationAotProcessor extends ContextAotProcessor {
@@ -65,20 +67,23 @@ protected GenericApplicationContext prepareApplicationContext(Class<?> applicati
6567
}
6668

6769
public static void main(String[] args) throws Exception {
68-
int requiredArgs = 6;
70+
int requiredArgs = 7;
6971
Assert.state(args.length >= requiredArgs, () -> "Usage: " + SpringApplicationAotProcessor.class.getName()
70-
+ " <applicationMainClass> <sourceOutput> <resourceOutput> <classOutput> <groupId> <artifactId> <originalArgs...>");
72+
+ " <applicationMainClass> <sourceOutput> <resourceOutput> <classOutput> <groupId> <artifactId> <artifactTypes> <originalArgs...>");
7173
Class<?> application = Class.forName(args[0]);
72-
Settings settings = Settings.builder()
74+
Settings.Builder builder = Settings.builder()
7375
.sourceOutput(Paths.get(args[1]))
7476
.resourceOutput(Paths.get(args[2]))
7577
.classOutput(Paths.get(args[3]))
7678
.groupId((StringUtils.hasText(args[4])) ? args[4] : "unspecified")
77-
.artifactId(args[5])
78-
.build();
79+
.artifactId(args[5]);
80+
String[] artifactTypes = args[6].split(",");
81+
for (String artifactType : artifactTypes) {
82+
builder.generatedArtifact(GeneratedArtifact.valueOf(artifactType));
83+
}
7984
String[] applicationArgs = (args.length > requiredArgs) ? Arrays.copyOfRange(args, requiredArgs, args.length)
8085
: new String[0];
81-
new SpringApplicationAotProcessor(application, settings, applicationArgs).process();
86+
new SpringApplicationAotProcessor(application, builder.build(), applicationArgs).process();
8287
}
8388

8489
/**

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mavenVersion=3.9.10
1919
mockitoVersion=5.19.0
2020
nativeBuildToolsVersion=0.11.0
2121
snakeYamlVersion=2.4
22-
springFrameworkVersion=7.0.0-M8
22+
springFrameworkVersion=7.0.0-SNAPSHOT
2323
springFramework60xVersion=6.0.23
2424
tomcatVersion=11.0.10
2525
nullabilityPluginVersion=0.0.4

0 commit comments

Comments
 (0)