At https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/kotlin/org/springframework/context/support/BeanDefinitionDsl.kt the comment shows how to define Spring Beans via the new "Functional bean definition Kotlin DSL". I also found https://github.com/sdeleuze/spring-kotlin-functional. However, this example uses just plain Spring and not Spring Boot. Any hint how to use the DSL together with Spring Boot is appreciated.
4 Answers
Spring Boot is based on Java Config, but should allow experimental support of user-defined functional bean declaration DSL via ApplicationContextInitializer
support as described here.
In practice, you should be able to declare your beans for example in a Beans.kt
file containing a beans()
function.
fun beans() = beans {
// Define your bean with Kotlin DSL here
}
Then in order to make it taken in account by Boot when running main()
and tests, create an ApplicationContextInitializer
class as following:
class BeansInitializer : ApplicationContextInitializer<GenericApplicationContext> {
override fun initialize(context: GenericApplicationContext) =
beans().initialize(context)
}
And ultimately, declare this initializer in your application.properties
file:
context.initializer.classes=com.example.BeansInitializer
You will find a full example here and can also follow this issue about dedicated Spring Boot support for functional bean registration.
-
Two questions regarding your answer: * This initialisation will be picked up by the test setup with using a
SpringRunner
with JUnit, right? * Is there any other way of having this behaviour without having to createproperties
files, including this initialisation being picked up on tests? Thanks! Mar 3, 2018 at 20:22 -
-
1Side note: we are currently exploring full functional bean definition for Boot with Java or Kotlin DSL in github.com/spring-projects/spring-fu incubator project. Feb 7, 2019 at 9:21
-
What if I want to override a bean? I added allow-bean-definition-overriding: true and am trying to declare a test bean via @Bean but it seems to be ignored. I have tried an exact same setup(basically, just copy pasted) on a project withotu bean DSL and it worked.– yuranosApr 1, 2019 at 12:58
-
Declaring the initializer like that will disable all other ones provided by spring boot, won't it? Apr 12, 2020 at 18:25
Another way to do it in Spring Boot would be :
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args) {
addInitializers(
beans {
// Define your bean with Kotlin DSL here
}
)
}
}
-
4The drawback of that approach is that the initializer won't be taken in account for tests. May 31, 2019 at 8:22
You can define your beans in *Config.kt file and implement initalize method of ApplicationContextInitializer interface.
override fun initialize(applicationContext: GenericApplicationContext) {
....
}
Some bean definition here.
bean<XServiceImpl>("xService")
bean("beanName") {
BeanConstructor(ref("refBeanName"))
}
That same example project you mentioned has a boot git branch, with the BeanDefinitionDsl configuration for Spring Boot in a Beans.kt
file. That is not how you should use git branches...
@Configuration
class with an@Bean
method returning the result ofbeans {...}
. Then I got the exception"... No qualifying bean of type '...' available ..."
when I remove@Service
and declare the service class inside thebeans {...}
lambda above.