You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.6 KiB
114 lines
3.6 KiB
[[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<Foo>() |
|
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<Foo>() |
|
registerBean<Bar>() |
|
} |
|
---- |
|
|
|
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<Bar>()` 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<Foo>() |
|
bean<Bar>() |
|
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]. |
|
|
|
|
|
|
|
|
|
|