What is the EK9 equivalent of Spring @Bean and @Configuration?

← Dependency Injection · Ref: Q326

EK9 replaces Spring's @Configuration classes and @Bean methods with the 'defines application' construct. The application definition is where you register concrete implementations against abstract types.

SPRING @BEAN VS EK9 APPLICATION REGISTRATION

Spring uses @Configuration with @Bean methods:

  @Configuration
  class AppConfig {
    @Bean DataSource dataSource() { return new HikariDataSource(); }
  }

EK9 uses explicit registration in the application:

  defines application
    MyApp
      register HikariDataSource() as DataSource

EXPLICIT CONSTRUCTION

In Spring, @Bean methods can contain arbitrary construction logic. In EK9, the register statement calls the component's constructor directly. Complex construction logic belongs in the component's constructor, not in configuration.

ORDERING IS EXPLICIT

Spring resolves bean creation order automatically (and sometimes gets it wrong). EK9 requires registration in dependency order: dependencies before dependents. The compiler validates this ordering at compile time (see Q228).

NO CONDITIONAL BEANS

Spring has @Conditional, @Profile, @ConditionalOnProperty for conditional bean creation. EK9 does not support conditional registration. If you need different configurations, define different applications. This eliminates an entire class of 'hidden missing bean' bugs.

See Q227 for compile-time validation. See Q228 for registration ordering. See Q324 for @Autowired equivalent. See Q325 for @Component equivalent.

Example

defines module qa.di.spring.bean.config

  defines component

    CacheService as abstract
      lookup() as abstract
        -> key as String
        <- hit as String?

      default operator ?

    InMemoryCache is CacheService
      override lookup()
        -> key as String
        <- hit as String: "cached:" + key

      default operator ?

    DataService as abstract
      fetch() as abstract
        -> query as String
        <- result as String?

      default operator ?

    CachedDataService is DataService
      cache as CacheService!

      override fetch()
        -> query as String
        <- result <- String()
        result: cache.lookup(query)

      default operator ?

  defines application

    <?-
      This application definition replaces @Configuration class.
      Each register statement replaces a @Bean method.
    -?>
    BeanConfigApp
      register InMemoryCache() as CacheService
      register CachedDataService() as DataService

  defines program

    BeanConfigDemo() with application of BeanConfigApp
      stdout <- Stdout()

      // === APPLICATION DEFINITION REPLACES @Configuration ===

      dataService as DataService!

      result <- dataService.fetch("users")
      stdout.println(result)

      stdout.println("Application construct replaces @Configuration + @Bean")

Common mistakes

E08200 — CachedDataService injects CacheService, so CacheService must be registered first. Unlike Spring which resolves order automatically, EK9 requires explicit dependency-first ordering. See ek9 -h E08200 for details.

Incorrect:

register CachedDataService() as DataService
      register InMemoryCache() as CacheService

Correct:

register InMemoryCache() as CacheService
      register CachedDataService() as DataService

E08150 — Injection fields must use the abstract type. The application maps concrete to abstract via 'register X() as Y', and fields inject the abstract Y. See ek9 -h E08150 for details.

Incorrect:

cache as InMemoryCache!

Correct:

cache as CacheService!
Other ways to ask this
  • How do I configure bean creation in EK9?
  • What replaces @Configuration classes in EK9?
  • How do I register third-party types for injection in EK9?

Coming from another language?

Java Spring: @Configuration + @Bean methods, auto-wiring, @Conditional/@Profile for conditional beans, FactoryBean for complex creation. Guice: Module.configure() with bind() statements. .NET: ConfigureServices with AddTransient/AddScoped/AddSingleton. Python: manual construction or DI frameworks. Go: wire for compile-time DI, manual construction. EK9: 'defines application' with explicit 'register' statements, dependency ordering enforced by compiler, no conditional registration.

Keywords: register, explicit, conditional, configuration, application, inject, create, spring, migration, bean, factory, dependency