Why Spring Boot 3 Dropped spring.factories and How to Migrate to imports Files

Spring Boot 3 removes the long‑standing spring.factories mechanism to improve startup speed, modularity, conditional loading, and GraalVM native‑image support, introducing per‑type imports files as a static, organized replacement, and this guide explains the reasons, benefits, and step‑by‑step migration process.

Architecture Digest
Architecture Digest
Architecture Digest
Why Spring Boot 3 Dropped spring.factories and How to Migrate to imports Files

1. Introduction

Spring Boot 3.0 brings a major change by removing the spring.factories file that was the core of auto‑configuration and extension mechanisms in earlier versions. Developers need to understand the new mechanism and migration strategy.

2. What is spring.factories

2.1 Basic concept

spring.factories

is a configuration file located under META-INF/ that uses a variant of Java's Service Provider Interface (SPI) to declare implementation classes, enabling Spring Boot's auto‑configuration and extension point registration.

2.2 Main uses

Before Spring Boot 3.0, the file was used for:

Auto‑configuration class registration

Listener and other extension point declarations

2.3 How it works

At startup, SpringFactoriesLoader scans all JARs for META-INF/spring.factories, reads the entries, and loads the corresponding classes, following a "convention over configuration" approach.

public final class SpringFactoriesLoader {
    // ...
    public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
        // ... load META-INF/spring.factories ...
    }
    // ...
}

3. Why spring.factories was removed

3.1 Performance issues

The scanning of all JARs at startup can be time‑consuming in projects with many dependencies, hurting startup performance.

3.2 Lack of modular support

Java 9+ module system (JPMS) conflicts with class‑path scanning; spring.factories cannot cleanly support modules.

3.3 No conditional loading

Configurations are static; conditional loading requires loading all classes into memory before evaluating conditions.

3.4 Scattered configuration

In large projects the file is spread across many JARs, making global view and management difficult.

3.5 GraalVM native image support

Dynamic class‑path scanning conflicts with GraalVM's ahead‑of‑time (AOT) compilation, static analysis, and reflection requirements.

4. Alternative: imports files

4.1 New mechanism introduction

Spring Boot 3.0 introduces imports files under META-INF/spring/, one file per extension point type (e.g., AutoConfiguration.imports).

imports file layout
imports file layout

4.2 Advantages

Better performance: each file contains only relevant classes.

Java module compatibility.

Simpler configuration: one fully‑qualified class name per line.

Clearer organization.

4.3 Comparison

Old way ( spring.factories):

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.FooAutoConfiguration,\
com.example.BarAutoConfiguration

New way ( AutoConfiguration.imports):

com.example.FooAutoConfiguration
com.example.BarAutoConfiguration

5. Migration guide

5.1 Auto‑configuration class migration

Move entries from spring.factories to

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

:

// Original spring.factories entry
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyAutoConfiguration

// New imports file
com.example.MyAutoConfiguration

5.2 Other extension points

Spring Boot still supports spring.factories for legacy types, but new projects should prefer imports files.

5.3 Custom extension points

Create a custom imports file and load it similarly to the built‑in loader.

public class MyExtensionLoader {
    public List<MyExtension> loadExtensions() {
        return SpringFactoriesLoader.loadFactoryNames(MyExtension.class, null);
    }
}

6. Changes to SpringFactoriesLoader

6.1 API changes

Deprecated loadFactories method; new loadFactoryNames reads imports files.

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    // Load corresponding imports file
}

6.2 Compatibility

Spring Boot 3.0 still supports spring.factories for backward compatibility, but recommends the new mechanism for new code.

7. Practical example

7.1 Create custom auto‑configuration

@ConfigurationProperties(prefix = "myapp")
public class MyProperties {
    private boolean enabled = true;
    private String name = "default";
    // getters and setters
}

@AutoConfiguration
@EnableConfigurationProperties(MyProperties.class)
@ConditionalOnProperty(prefix = "myapp", name = "enabled", havingValue = "true", matchIfMissing = true)
public class MyAutoConfiguration {
    private final MyProperties properties;
    public MyAutoConfiguration(MyProperties properties) { this.properties = properties; }
    @Bean
    @ConditionalOnMissingBean
    public MyService myService() {
        return new MyServiceImpl(properties.getName());
    }
}

7.2 Register auto‑configuration

Create

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

containing:

com.example.MyAutoConfiguration

7.3 Project structure

myproject/
├── src/main/java/com/example/
│   ├── MyProperties.java
│   ├── MyService.java
│   ├── MyServiceImpl.java
│   └── MyAutoConfiguration.java
└── src/main/resources/META-INF/spring/
    └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

8. Performance comparison

Typical medium‑size Spring Boot applications show noticeable startup time reduction after switching to imports files.

performance chart
performance chart

9. Frequently asked questions

9.1 Compatibility issues

Existing libraries that still use spring.factories continue to work because Spring Boot retains support for the old file.

9.2 Migration effort

Large projects can migrate incrementally: first move auto‑configuration classes, then other extension points.

9.3 Custom loaders

For custom loaders, follow Spring Boot’s new imports‑based approach to provide static configuration.

10. Spring Boot 3.0 and GraalVM integration

10.1 GraalVM overview

GraalVM can compile Java applications into native images with fast startup, low memory usage, and no JVM required.

Fast startup (milliseconds)

Low memory footprint

Ahead‑of‑time compilation

10.2 Challenges for Spring Boot

Dynamic features such as runtime class‑path scanning and reflection clash with GraalVM’s static analysis.

graalvm challenges diagram
graalvm challenges diagram

10.3 Imports files solve the compatibility problem

Static analyzable configuration

Clear file paths avoid runtime scanning

Reduced reflection usage

Build‑time processing for AOT

10.4 Spring Boot AOT engine

public class SpringAotProcessor {
    public void process() {
        // 1. Read imports files instead of scanning spring.factories
        List<String> configurations = readImportsFiles();
        // 2. Evaluate conditions at build time
        List<String> effectiveConfigurations = evaluateConditions(configurations, buildTimeProperties);
        // 3. Generate proxies
        generateProxies(effectiveConfigurations);
        // 4. Generate reflection config
        generateReflectionConfig(effectiveConfigurations);
        // 5. Generate resources config
        generateResourcesConfig();
    }
}

10.5 GraalVM integration example

Configure Maven with spring-native and spring-aot-maven-plugin to build a native image, and register auto‑configuration via imports files.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.experimental</groupId>
        <artifactId>spring-native</artifactId>
        <version>${spring-native.version}</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <image>
                    <builder>paketobuildpacks/builder:tiny</builder>
                    <env>
                        <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
                    </env>
                </image>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-aot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>generate</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

10.6 Performance comparison: JVM vs GraalVM native image

jvm vs native performance chart
jvm vs native performance chart

10.7 Best practices

Reduce reflection: prefer constructor injection.

Avoid dynamic proxies where possible.

Perform static initialization at build time.

Register all configuration classes via imports files.

Use @NativeHint to provide GraalVM hints.

10.8 Limitations and considerations

Dynamic features (runtime class loading, bytecode generation) are limited.

All reflective accesses must be declared.

Native image build time is longer; plan CI/CD accordingly.

Debugging native images is more complex than JVM debugging.

Third‑party libraries may need GraalVM‑specific adjustments.

By removing spring.factories and introducing imports files, Spring Boot 3.0 significantly improves integration with GraalVM, enabling developers to build high‑performance, low‑latency cloud‑native applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.