How does EK9 DI compare to Spring Boot auto-configuration?
← Dependency Injection · Ref: Q327
Spring Boot's auto-configuration automatically creates beans based on classpath contents and properties. EK9 deliberately rejects auto-configuration in favor of explicit registration.
SPRING BOOT AUTO-CONFIGURATION
Spring Boot scans for @AutoConfiguration classes, evaluates @Conditional annotations, and creates beans based on what's on the classpath. A single dependency like spring-boot-starter-web auto-configures an embedded Tomcat, Jackson, DispatcherServlet, and dozens of other beans.
WHY EK9 REJECTS AUTO-CONFIGURATION
1. INVISIBLE BEHAVIOUR: Auto-configured beans appear from nowhere. Developers cannot tell which beans exist without running the application and inspecting the context.
2. FRAGILE ORDERING: Auto-configuration order depends on classpath scanning, which can change between builds. This causes intermittent failures.
3. CONDITIONAL COMPLEXITY: @ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty create a combinatorial explosion of possible configurations.
4. DEBUGGING NIGHTMARE: When auto-configuration goes wrong, developers must trace through AbstractAutowireCapableBeanFactory and dozens of post-processors.
EK9'S EXPLICIT APPROACH
In EK9, every component registration is visible in the application definition. There is no magic. If you can read the 'defines application' section, you know exactly what components exist.
BENEFITS OF EXPLICITNESS
1. AUDITABLE: Security teams can review exactly what's registered
2. PREDICTABLE: Same registration, same behavior, every time
3. COMPILE-TIME VERIFIED: Compiler checks completeness and ordering
4. AI-FRIENDLY: AI can read and generate correct registrations
See Q227 for compile-time validation. See Q326 for @Bean equivalent. See Q332 for runtime overhead comparison.
Example
defines module qa.di.spring.boot.comparison defines component Logger as abstract log() as abstract -> message as String <- output as String? default operator ? ConsoleLogger is Logger override log() -> message as String <- output as String: "[LOG] " + message default operator ? Repository as abstract find() as abstract -> identifier as String <- record as String? default operator ? SimpleRepository is Repository logger as Logger! override find() -> identifier as String <- record <- String() record: logger.log("Found: " + identifier) default operator ? AppController as abstract handle() as abstract -> request as String <- response as String? default operator ? MainController is AppController repo as Repository! override handle() -> request as String <- response <- String() response: repo.find(request) default operator ? defines application <?- Every registration is explicit and visible. No auto-configuration, no classpath magic. -?> ExplicitApp register ConsoleLogger() as Logger register SimpleRepository() as Repository register MainController() as AppController defines program SpringBootComparisonDemo() with application of ExplicitApp stdout <- Stdout() // === EXPLICIT REGISTRATION VS AUTO-CONFIGURATION === controller as AppController! result <- controller.handle("user-123") stdout.println(result) stdout.println("Every component explicitly registered and verified")
Common mistakes
E08200 — Unlike Spring Boot auto-configuration which resolves order automatically, EK9 requires dependencies registered before dependents. MainController depends on Repository which depends on Logger, so Logger must come first. See ek9 -h E08200 for details.
Incorrect:
register MainController() as AppController register SimpleRepository() as Repository register ConsoleLogger() as Logger
Correct:
register ConsoleLogger() as Logger register SimpleRepository() as Repository register MainController() as AppController
E50001 — Renaming the variable means later references to 'result' become unresolved, triggering E50001. See ek9 -h E50001 for details.
Incorrect:
resultXYZ <- controller.handle("user-123")
Correct:
result <- controller.handle("user-123")
Other ways to ask this
- Does EK9 have auto-configuration like Spring Boot?
- How does EK9 handle what Spring Boot starters provide?
- What is different between Spring Boot and EK9 dependency injection?
Coming from another language?
Java Spring Boot: @SpringBootApplication triggers auto-configuration, starters provide pre-configured beans, @Conditional for conditional creation, spring.factories/META-INF for discovery. Quarkus: build-time configuration similar to EK9 philosophy. Micronaut: compile-time DI, closer to EK9 approach. .NET: Host.CreateDefaultBuilder with auto-configuration. EK9: explicit registration only, no auto-configuration, no classpath scanning, compile-time validation.
Keywords: inject, starter, configuration, spring boot, explicit, scanning, invisible, dependency, registration, auto, migration, classpath