Permalink
Browse files

Support autowiring by constructor in Kotlin bean DSL

Issue: SPR-16014
  • Loading branch information...
sdeleuze committed Sep 26, 2017
1 parent 0e7e95c commit 23497a7ece7aac1591187b46f4b601d2f48764e0
@@ -17,6 +17,7 @@
package org.springframework.context.support
import org.springframework.beans.factory.config.BeanDefinitionCustomizer
import org.springframework.beans.factory.support.AbstractBeanDefinition
import org.springframework.context.ApplicationContextInitializer
import org.springframework.core.env.ConfigurableEnvironment
import java.util.function.Supplier
@@ -29,9 +30,7 @@ import java.util.function.Supplier
* ```
* beans {
* bean<UserHandler>()
* bean {
* Routes(ref(), ref())
* }
* bean<Routes>()
* bean<WebHandler>("webHandler") {
* RouterFunctions.toWebHandler(
* ref<Routes>().router(),
@@ -100,6 +99,35 @@ open class BeanDefinitionDsl(private val condition: (ConfigurableEnvironment) ->
PROTOTYPE
}
/**
* Autowire enum constants.
*/
enum class Autowire {
/**
* Autowire constant that indicates no externally defined autowiring
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_NO
*/
NO,
/**
* Autowire constant that indicates autowiring bean properties by name
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_BY_NAME
*/
BY_NAME,
/**
* Autowire constant that indicates autowiring bean properties by type
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE
*/
BY_TYPE,
/**
* Autowire constant that indicates autowiring the greediest constructor that can be satisfied
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR
*/
CONSTRUCTOR
}
/**
* Provide read access to some application context facilities.
* @constructor Create a new bean definition context.
@@ -134,6 +162,7 @@ open class BeanDefinitionDsl(private val condition: (ConfigurableEnvironment) ->
* @param scope Override the target scope of this bean, specifying a new scope name.
* @param isLazyInit Set whether this bean should be lazily initialized.
* @param isPrimary Set whether this bean is a primary autowire candidate.
* @param autowireMode Set the autowire mode, `Autowire.CONSTRUCTOR` by default
* @param isAutowireCandidate Set whether this bean is a candidate for getting autowired into some other bean.
* @see GenericApplicationContext.registerBean
* @see org.springframework.beans.factory.config.BeanDefinition
@@ -142,6 +171,7 @@ open class BeanDefinitionDsl(private val condition: (ConfigurableEnvironment) ->
scope: Scope? = null,
isLazyInit: Boolean? = null,
isPrimary: Boolean? = null,
autowireMode: Autowire = Autowire.CONSTRUCTOR,
isAutowireCandidate: Boolean? = null) {
registrations.add {
@@ -150,6 +180,9 @@ open class BeanDefinitionDsl(private val condition: (ConfigurableEnvironment) ->
isLazyInit?.let { bd.isLazyInit = isLazyInit }
isPrimary?.let { bd.isPrimary = isPrimary }
isAutowireCandidate?.let { bd.isAutowireCandidate = isAutowireCandidate }
if (bd is AbstractBeanDefinition) {
bd.autowireMode = autowireMode.ordinal
}
}
when (name) {
@@ -162,12 +195,21 @@ open class BeanDefinitionDsl(private val condition: (ConfigurableEnvironment) ->
/**
* Declare a bean definition using the given supplier for obtaining a new instance.
*
* @param name the name of the bean
* @param scope Override the target scope of this bean, specifying a new scope name.
* @param isLazyInit Set whether this bean should be lazily initialized.
* @param isPrimary Set whether this bean is a primary autowire candidate.
* @param autowireMode Set the autowire mode, `Autowire.NO` by default
* @param isAutowireCandidate Set whether this bean is a candidate for getting autowired into some other bean.
* @param function the bean supplier function
* @see GenericApplicationContext.registerBean
* @see org.springframework.beans.factory.config.BeanDefinition
*/
inline fun <reified T : Any> bean(name: String? = null,
scope: Scope? = null,
isLazyInit: Boolean? = null,
isPrimary: Boolean? = null,
autowireMode: Autowire = Autowire.NO,
isAutowireCandidate: Boolean? = null,
crossinline function: BeanDefinitionContext.() -> T) {
@@ -176,6 +218,9 @@ open class BeanDefinitionDsl(private val condition: (ConfigurableEnvironment) ->
isLazyInit?.let { bd.isLazyInit = isLazyInit }
isPrimary?.let { bd.isPrimary = isPrimary }
isAutowireCandidate?.let { bd.isAutowireCandidate = isAutowireCandidate }
if (bd is AbstractBeanDefinition) {
bd.autowireMode = autowireMode.ordinal
}
}
registrations.add {
@@ -192,9 +192,7 @@ how beans are registered.
----
fun beans() = beans {
bean<UserHandler>()
bean {
Routes(ref(), ref())
}
bean<Routes>()
bean<WebHandler>("webHandler") {
RouterFunctions.toWebHandler(
ref<Routes>().router(),
@@ -222,9 +220,7 @@ fun beans() = beans {
}
----
In this example, `Routes(ref(), ref())` is the equivalent of `Routes(ref<UserHandler>(), ref<MessageSource>())`
(types are not required thanks to Kotlin type inference) where `ref<UserHandler>()`
is a shortcut for `applicationContext.getBean(UserHandler::class.java)`.
In this example, `ref<Routes>()` is a shortcut for `applicationContext.getBean(Routes::class.java)`.
This `beans()` function can then be used to register beans on the application context.
@@ -242,7 +238,7 @@ This DSL is programmatic, thus it allows custom registration logic of beans
via an `if` expression, a `for` loop or any other Kotlin constructs.
====
See https://github.com/sdeleuze/spring-kotlin-functional/blob/3d12ab102c28f4761bd6a0736e2f585713eb2243/src/main/kotlin/functional/Beans.kt[spring-kotlin-functional beans declaration]
See https://github.com/sdeleuze/spring-kotlin-functional/blob/master/src/main/kotlin/functional/Beans.kt[spring-kotlin-functional beans declaration]
for a concrete example.
[NOTE]

0 comments on commit 23497a7

Please sign in to comment.