Bean Definition DSL
Spring Framework 支持使用 Lambda 表达式(作为 XML 或 Java 配置(@Configuration
和 @Bean
)的替代方式)以函数方式注册 Bean。简而言之,它允许你使用作为 FactoryBean
的 Lambda 表达式来注册 Bean。此机制非常有效,因为它不需要任何反射或 CGLIB 代理。
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.
例如,在 Java 中,你可以编写以下内容:
In Java, you can, for example, write the following:
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)));
而在 Kotlin 中,使用实际类型参数和 GenericApplicationContext
Kotlin 扩展,你可以编写以下内容:
In Kotlin, with reified type parameters and GenericApplicationContext
Kotlin extensions,
you can instead write the following:
class Foo
class Bar(private val foo: Foo)
val context = GenericApplicationContext().apply {
registerBean<Foo>()
registerBean { Bar(it.getBean()) }
}
当类 Bar
具有单个构造函数时,你甚至可以仅指定 Bean 类,构造函数参数将根据类型自动装配:
When the class Bar
has a single constructor, you can even just specify the bean class,
the constructor parameters will be autowired by type:
val context = GenericApplicationContext().apply {
registerBean<Foo>()
registerBean<Bar>()
}
为了允许更具声明性的方法和更简洁的语法,Spring 框架提供了https://docs.spring.io/spring-framework/docs/current/kdoc-api/spring-context/org.springframework.context.support/-bean-definition-dsl/index.html[Kotlin Bean 定义 DSL] 它通过一个简洁的声明性 API 声明 ApplicationContextInitializer
,使您可以处理配置文件和 `Environment`以自定义注册 Bean 的方式。
In order to allow a more declarative approach and cleaner syntax, Spring Framework provides
a 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>()
orbean(::myRouter)
, parameters are autowired by type -
The
FooBar
bean will be registered only if thefoobar
profile is active
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 {
// ...
}
此 DSL 是以编程方式进行的,这意味着它允许通过 |
This DSL is programmatic, meaning it allows custom registration logic of beans
through an |
然后,你可以使用此 beans()
函数在应用上下文中注册 Bean,如下面的示例所示:
You can then use this beans()
function to register beans on the application context,
as the following example shows:
val context = GenericApplicationContext().apply {
myBeans.initialize(this)
refresh()
}
Spring Boot 基于 JavaConfig 和 尚未提供对函数 bean 定义的特定支持,但你可以通过 Spring Boot 的 |
Spring Boot is based on JavaConfig and
does not yet provide specific support for functional bean definition,
but you can experimentally use functional bean definitions through Spring Boot’s |