|
对于最新稳定版本,请使用 Spring Framework 7.0.6! |
Bean 定义 DSL
Spring Framework 支持使用 Lambda 表达式以函数式方式注册 Bean,作为 XML 或 Java 配置(@Configuration 和 @Bean)的替代方案。简而言之,它允许你通过一个充当 FactoryBean 的 Lambda 表达式来注册 Bean。
这种机制非常高效,因为它不需要任何反射或 CGLIB 代理。
在 Java 中,例如,你可以编写如下代码:
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 扩展,
你可以改写为如下代码:
class Foo
class Bar(private val foo: Foo)
val context = GenericApplicationContext().apply {
registerBean<Foo>()
registerBean { Bar(it.getBean()) }
}
当类 Bar 只有一个构造函数时,你甚至只需指定 bean 类,
构造函数参数将按类型自动装配:
val context = GenericApplicationContext().apply {
registerBean<Foo>()
registerBean<Bar>()
}
为了支持更声明式的编程方式和更简洁的语法,Spring Framework 提供了
Kotlin Bean 定义 DSL。
它通过一个清晰的声明式 API 声明一个 ApplicationContextInitializer,
使你可以处理 Profiles 和 Environment,以自定义 Bean 的注册方式。
在下面的示例中请注意:
-
类型推断通常可以避免为 bean 引用(例如
ref("bazBean"))显式指定类型。 -
可以使用 Kotlin 的顶层函数,通过可调用引用(例如本例中的
bean(::myRouter))来声明 Bean。 -
指定
bean<Bar>()或bean(::myRouter)时,参数会按类型自动装配。 -
仅当
FooBar配置文件处于激活状态时,foobarBean 才会被注册。
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 是程序化的,这意味着它允许通过 if 表达式、for 循环或任何其他 Kotlin 结构来实现自定义的 Bean 注册逻辑。 |
然后,您可以使用这个 beans() 函数在应用上下文中注册 bean,如下例所示:
val context = GenericApplicationContext().apply {
myBeans.initialize(this)
refresh()
}
Spring Boot 基于 JavaConfig,
目前尚未提供对函数式 Bean 定义的特定支持,
但你可以通过 Spring Boot 的 ApplicationContextInitializer 支持来实验性地使用函数式 Bean 定义。
有关更多详细信息和最新动态,请参阅 此 Stack Overflow 回答。
另请参阅在 Spring Fu 孵化器 中开发的实验性 Kofu DSL。 |