Why use spring.factories for Spring Boot auto-configuration instead of annotations?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Spring Boot auto-configuration was historically discovered through metadata files such as spring.factories instead of relying on component scanning alone. The reason is control: auto-configuration has to be found from dependency jars before normal application beans are created, and it has to load in a deterministic order. The important design point is not the filename itself, but the fact that Boot uses explicit registration metadata rather than hoping annotations will be discovered by scanning.
Why Annotation Scanning Alone Is Not Enough
A plain annotation such as @Configuration only helps after Spring has already decided what to scan. That works for application code, but auto-configuration lives in external starter jars that the application did not explicitly scan.
If Boot depended only on component scanning, every starter would need to be included in scan base packages, which would be fragile, slow, and easy to misconfigure.
With metadata registration, Boot can ask:
- which auto-configurations exist
- in which order they should be considered
- which conditions decide whether they activate
That is much more deterministic than annotation discovery.
What spring.factories Historically Did
Historically, a starter jar registered its auto-configuration classes in META-INF/spring.factories. Boot read that metadata early and imported the listed configuration classes conditionally.
Example auto-configuration:
And the metadata entry:
That explicit registration step is what made the class discoverable as auto-configuration rather than ordinary application configuration.
Why Explicit Metadata Is Better for Starters
There are several practical advantages:
- Starter jars stay decoupled from application package scanning.
- Boot can evaluate auto-configurations in a predictable import phase.
- Startup remains faster than broad classpath scanning.
- Library authors can publish plug-in style configuration cleanly.
This is particularly important for third-party starters. A reusable starter should work when added as a dependency, not only when the consumer manually extends scan rules.
Conditions Belong with the Configuration Class
The metadata file answers discovery. The annotations answer activation. Those are different concerns.
The configuration class still uses conditional annotations such as:
- '
@ConditionalOnClass' - '
@ConditionalOnMissingBean' - '
@ConditionalOnProperty'
That means Boot first discovers the class from metadata, then decides whether it should actually contribute beans.
Why This Is Cleaner Than Forcing @ComponentScan
Using @ComponentScan for starters would blur the line between library internals and public auto-configuration API. It would also make ordering harder and create more accidental beans.
Auto-configuration should be opt-in by dependency and condition, not opt-in by scanning arbitrary package trees.
Modern Boot Context
In newer Spring Boot generations, the registration mechanism evolved, but the architectural reason stayed the same: explicit metadata-driven discovery is preferred over annotation scanning for framework-level auto-configuration. So even if a project is no longer centered on spring.factories, the answer to the design question is still metadata, ordering, and controlled discovery.
Small Starter Example
If you were building a starter, the structure would look like this:
Consumer code does not scan your starter package. It just adds the dependency, and Boot discovers the configuration through metadata.
Common Pitfalls
- Assuming
@Configurationalone makes a class an auto-configuration candidate. - Confusing class discovery with activation conditions.
- Using component scanning in starter jars and leaking unintended beans.
- Ignoring ordering concerns between multiple auto-configurations.
- Forgetting that framework infrastructure and application scanning solve different problems.
Summary
- Auto-configuration needs explicit discovery from dependency jars, not normal package scanning.
- '
spring.factorieshistorically provided that early metadata-driven registration.' - Conditional annotations still control whether discovered configuration activates.
- Metadata-based discovery is faster, more deterministic, and cleaner for starter libraries.
- Even in newer Boot setups, the design rationale remains the same.
Related reading
- Why use try finally with an empty try block?
- Why we call Thread.start method which in turns calls run method?
- Why would a static nested interface be used in Java?
- Why would an Enum implement an Interface?
- Why would you catch InterruptedException to call Thread.currentThread.interrupt?
- Why would you ever implement finalize()?
- Wildfly 17 Distributed Infinispan Cache Session not found
- Will Try / Finally without the Catch bubble the exception?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.