https://github.com/patbaumgartner/spring-boot-autoconfiguration-optimizer
https://github.com/patbaumgartner/spring-boot-autoconfiguration-optimizer
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/patbaumgartner/spring-boot-autoconfiguration-optimizer
- Owner: patbaumgartner
- License: other
- Created: 2026-03-09T06:53:55.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-04-20T12:17:42.000Z (about 1 month ago)
- Last Synced: 2026-04-20T14:36:40.004Z (about 1 month ago)
- Language: Java
- Size: 3.53 MB
- Stars: 2
- Watchers: 0
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# Spring Boot Autoconfiguration Optimizer
[](https://github.com/patbaumgartner/spring-boot-autoconfiguration-optimizer/actions/workflows/ci.yml)
[](https://github.com/patbaumgartner/spring-boot-autoconfiguration-optimizer/actions/workflows/benchmarks.yml)
[](https://search.maven.org/artifact/com.patbaumgartner/autoconfiguration-optimizer-core)
[](https://plugins.gradle.org/plugin/com.patbaumgartner.autoconfiguration-optimizer)
[](https://opensource.org/licenses/Apache-2.0)
[](https://adoptium.net/)
[](https://spring.io/projects/spring-boot)
> Reduce Spring Boot startup time by automatically detecting and excluding unused auto-configurations using a one-time training run.
## Why Bother?
Spring Boot evaluates hundreds of `@Conditional` annotations at every startup, even for auto-configurations that will never apply to your application. This optimizer records which ones actually matched during a training run and permanently skips the rest on every subsequent start.
The result: fewer condition evaluations, faster startup, and zero changes to your application code.
## How It Works
1. **Training Run**: Start your application once with training mode enabled. The optimizer captures every auto-configuration that passed its conditions and writes the list to `META-INF/autoconfiguration-optimizer.properties`. Commit this file so it is baked into subsequent builds. **This step is required to get any optimization benefit** - without the training file, the optimizer is a no-op.
2. **Inject**: Add the plugin to your build. The `inject` goal/task automatically embeds the optimizer core into your packaged JAR. No separate dependency declaration is needed.
3. **Subsequent Starts**: An `AutoConfigurationImportFilter` reads the file at startup and directly restricts which auto-configurations Spring Boot imports to only those in the training set.
4. **Safe by Default**: If the training file is missing (e.g., before the first training run), the optimizer does nothing and Spring Boot starts as usual.
```
Training Run Production Run
──────────────── ──────────────────────────────────
App starts normally AutoConfigurationImportFilter reads
with all auto-configs META-INF/autoconfiguration-
optimizer.properties
ConditionEvaluationReport │
records matched configs Filters candidate list to only
configs in the training set
Writes │
autoconfiguration- Spring Boot skips loading and
optimizer.properties condition evaluation for all
filtered-out configurations
```
### Why `AutoConfigurationImportFilter` Instead of `spring.autoconfigure.exclude`
The optimizer uses Spring Boot's `AutoConfigurationImportFilter` extension point rather than setting `spring.autoconfigure.exclude`. This is more efficient because:
- **Single pass**: The list of auto-configuration candidates is loaded only once by Spring Boot's `AutoConfigurationImportSelector`, not twice (once in an `EnvironmentPostProcessor` and once again inside the selector).
- **No string manipulation**: Filtering is done via a simple `boolean[]` array operation on the candidate strings with no comma-separated list building or property parsing required.
- **Right extension point**: The filter runs directly inside the auto-configuration import pipeline, at the earliest possible moment before any auto-configuration class is loaded or its conditions evaluated.
- **Forward-compatible**: `EnvironmentPostProcessor` is deprecated for removal in Spring Boot 4; `AutoConfigurationImportFilter` is the recommended approach.
## 🚀 Benchmark Results
Startup time benchmarks run automatically on every push to `main` against a [PetClinic](integration-tests/petclinic-sample)-like application (Web + JPA + Actuator + Cache + Validation) using Java 17, 21, and 25 on GitHub Actions runners.
> **[View the latest benchmark report →](../../actions/workflows/benchmarks.yml)**
> Download the `benchmark-report` artifact from the most recent successful run for exact numbers.
The actual improvement depends on how many Spring Boot starters your application uses. The more auto-configurations Spring Boot has to evaluate at startup, the more you gain.
## Quick Start
### Maven
Add the plugin to your `pom.xml`. The `inject` goal embeds the optimizer core into your packaged JAR with no explicit core dependency needed. Then run the `train` goal once to generate the optimizer properties file:
```xml
com.patbaumgartner
spring-boot-autoconfiguration-optimizer-maven-plugin
1.0.0
train
inject
com.example.MyApplication
-Xmx512m
-Dspring.profiles.active=training
120
```
Or run the training goal directly on the command line:
```bash
mvn com.patbaumgartner:spring-boot-autoconfiguration-optimizer-maven-plugin:train
# Generates target/classes/META-INF/autoconfiguration-optimizer.properties
```
Re-run training whenever your application's dependencies change significantly.
### Gradle
Apply the plugin: the optimizer core is automatically injected into your `bootJar` output:
```groovy
plugins {
id 'com.patbaumgartner.autoconfiguration-optimizer' version '1.0.0'
}
autoconfigurationOptimizer {
// Auto-detected from @SpringBootApplication.
// Set explicitly if auto-detection fails.
mainClass = 'com.example.MyApplication'
// Optional: extra JVM arguments passed to the training-run process
jvmArguments = ['-Xmx512m', '-Dspring.profiles.active=training']
// Optional: timeout in seconds (default: 120)
timeout = 120
}
```
Run the training step (automatically wired into `jar`/`bootJar`):
```bash
./gradlew bootJar
# Training, copy, and inject tasks run automatically before packaging
# Generates build/classes/java/main/META-INF/autoconfiguration-optimizer.properties
```
Re-run training whenever your application's dependencies change significantly.
## Configuration Reference
### Core Library Properties
| Property | Default | Description |
|---|---|---|
| `autoconfiguration.optimizer.enabled` | `true` | Enable/disable the optimizer |
| `autoconfiguration.optimizer.training-run` | `false` | Enable training mode |
| `autoconfiguration.optimizer.output-file` | `autoconfiguration-optimizer.properties` | Output file name |
| `autoconfiguration.optimizer.output-directory` | `.` | Output directory for training |
| `autoconfiguration.optimizer.exit-after-training` | `false` | Exit JVM after training |
### Maven Plugin Parameters (`train` goal)
| Parameter | Property | Default | Description |
|---|---|---|---|
| `mainClass` | `autoconfiguration.optimizer.mainClass` | auto-detected | Fully-qualified main class. Auto-detected from `@SpringBootApplication` scan or `start-class` property when omitted. |
| `jvmArguments` | `autoconfiguration.optimizer.jvmArguments` | _(none)_ | Additional JVM arguments passed to the training-run process. |
| `jar` | `autoconfiguration.optimizer.jar` | _(none)_ | Spring Boot executable JAR to run. When set, `mainClass` is ignored. |
| `timeout` | `autoconfiguration.optimizer.timeout` | `120` | Training run timeout in seconds. |
| `targetDirectory` | `autoconfiguration.optimizer.targetDirectory` | `${project.build.outputDirectory}/META-INF` | Directory where the properties file is copied after training. |
| `outputFile` | `autoconfiguration.optimizer.outputFile` | `autoconfiguration-optimizer.properties` | Name of the generated properties file. |
| `workingDirectory` | `autoconfiguration.optimizer.workingDirectory` | `${project.build.directory}` | Working directory for the training process. |
| `skip` | `autoconfiguration.optimizer.skip` | `false` | Skip the training run. |
### Gradle Plugin Extension (`autoconfigurationOptimizer`)
| Property | Default | Description |
|---|---|---|
| `mainClass` | auto-detected | Fully-qualified main class. Auto-detected from `@SpringBootApplication` scan when omitted. |
| `jvmArguments` | _(none)_ | Additional JVM arguments passed to the training-run process. |
| `jar` | _(none)_ | Spring Boot executable JAR to run. When set, `mainClass` is ignored. |
| `timeout` | `120` | Training run timeout in seconds. |
| `targetDirectory` | `build/classes/java/main/META-INF` | Directory where the properties file is copied after training. |
| `outputFile` | `autoconfiguration-optimizer.properties` | Name of the generated properties file. |
| `skip` | `false` | Skip the training run. |
## Spring Boot Compatibility
| Spring Boot | Java | Build Tool | Status |
|---|---|---|---|
| 4.0.x | 17, 21, 25 | Maven, Gradle 9 | ✅ Default |
> **Spring Boot 4.0** requires **Java 17 minimum** and is the default target for this library.
## Running Benchmarks Locally
```bash
# Build everything
mvn package -DskipTests
# Run benchmarks
./benchmarks/scripts/run-benchmarks-maven.sh \
integration-tests/petclinic-sample/target/autoconfiguration-optimizer-petclinic-sample-*.jar
# View the report
cat benchmarks/results/benchmark-report.md
```
Benchmarks also run automatically in CI on every push to `main` and results are available as [GitHub Actions artifacts](../../actions/workflows/benchmarks.yml).
## Project Structure
```
spring-boot-autoconfiguration-optimizer/
├── autoconfiguration-optimizer-core/ # Core library
├── spring-boot-autoconfiguration-optimizer-maven-plugin/ # Maven plugin
├── spring-boot-autoconfiguration-optimizer-gradle-plugin/ # Gradle plugin
├── integration-tests/
│ ├── petclinic-sample/ # Maven integration test app (PetClinic-like)
│ └── petclinic-sample-gradle/ # Gradle integration test app (shares sources with Maven sample)
└── benchmarks/ # Startup benchmarks + scripts
```
## Contributing
See [CODE_OF_CONDUCT.md](.github/CODE_OF_CONDUCT.md) for community standards.
## Security
See [SECURITY.md](SECURITY.md) for how to report security vulnerabilities.
## License
Apache License 2.0 - see [LICENSE](LICENSE) for details.