[[kotlin-bean-definition-dsl]] = Bean Definition DSL Spring Framework supports registering beans in a functional way by using lambdas as an alternative to XML or Java configuration (`@Configuration` and `@Bean`). In a nutshell, it lets you register beans with a lambda that acts as a `FactoryBean`. This mechanism is very efficient, as it does not require any reflection or CGLIB proxies. In Java, you can, for example, write the following: [source,java,indent=0] ---- class Foo {} class Bar { private final Foo foo; public Bar(Foo foo) { this.foo = foo; } } GenericApplicationContext context = new GenericApplicationContext(); context.registerBean(Foo.class); context.registerBean(Bar.class, () -> new Bar(context.getBean(Foo.class))); ---- In Kotlin, with reified type parameters and `GenericApplicationContext` Kotlin extensions, you can instead write the following: [source,kotlin,indent=0] ---- class Foo class Bar(private val foo: Foo) val context = GenericApplicationContext().apply { registerBean() registerBean { Bar(it.getBean()) } } ---- When the class `Bar` has a single constructor, you can even just specify the bean class, the constructor parameters will be autowired by type: [source,kotlin,indent=0] ---- val context = GenericApplicationContext().apply { registerBean() registerBean() } ---- In order to allow a more declarative approach and cleaner syntax, Spring Framework provides a {docs-spring-framework}/kdoc-api/spring-context/org.springframework.context.support/-bean-definition-dsl/index.html[Kotlin bean definition DSL] It declares an `ApplicationContextInitializer` through a clean declarative API, which lets you deal with profiles and `Environment` for customizing how beans are registered. In the following example notice that: * Type inference usually allows to avoid specifying the type for bean references like `ref("bazBean")` * It is possible to use Kotlin top level functions to declare beans using callable references like `bean(::myRouter)` in this example * When specifying `bean()` or `bean(::myRouter)`, parameters are autowired by type * The `FooBar` bean will be registered only if the `foobar` profile is active [source,kotlin,indent=0] ---- class Foo class Bar(private val foo: Foo) class Baz(var message: String = "") class FooBar(private val baz: Baz) val myBeans = beans { bean() bean() bean("bazBean") { Baz().apply { message = "Hello world" } } profile("foobar") { bean { FooBar(ref("bazBean")) } } bean(::myRouter) } fun myRouter(foo: Foo, bar: Bar, baz: Baz) = router { // ... } ---- NOTE: This DSL is programmatic, meaning it allows custom registration logic of beans through an `if` expression, a `for` loop, or any other Kotlin constructs. You can then use this `beans()` function to register beans on the application context, as the following example shows: [source,kotlin,indent=0] ---- val context = GenericApplicationContext().apply { myBeans.initialize(this) refresh() } ---- NOTE: Spring Boot is based on JavaConfig and https://github.com/spring-projects/spring-boot/issues/8115[does not yet provide specific support for functional bean definition], but you can experimentally use functional bean definitions through Spring Boot's `ApplicationContextInitializer` support. See https://stackoverflow.com/questions/45935931/how-to-use-functional-bean-definition-kotlin-dsl-with-spring-boot-and-spring-w/46033685#46033685[this Stack Overflow answer] for more details and up-to-date information. See also the experimental Kofu DSL developed in https://github.com/spring-projects/spring-fu[Spring Fu incubator].