跳到主要内容

Bean 定义 DSL

ChatGPT-4o 中英对照 Bean Definition 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)));
java

在 Kotlin 中,使用具体化的类型参数和 GenericApplicationContext Kotlin 扩展,你可以这样写:

class Foo

class Bar(private val foo: Foo)

val context = GenericApplicationContext().apply {
registerBean<Foo>()
registerBean { Bar(it.getBean()) }
}
kotlin

当类 Bar 只有一个构造函数时,你甚至只需指定 bean 类,构造函数的参数将通过类型自动装配:

val context = GenericApplicationContext().apply {
registerBean<Foo>()
registerBean<Bar>()
}
kotlin

为了允许更具声明性的方法和更简洁的语法,Spring Framework 提供了一个 Kotlin bean definition DSL。它通过一个简洁的声明式 API 声明了一个 ApplicationContextInitializer,这使您可以处理配置文件和 Environment,以自定义 bean 的注册方式。

在下面的例子中请注意:

  • 类型推断通常允许避免为 bean 引用指定类型,例如 ref("bazBean")

  • 可以使用 Kotlin 顶级函数通过可调用引用来声明 bean,例如在此示例中使用 bean(::myRouter)

  • 当指定 bean<Bar>()bean(::myRouter) 时,参数会通过类型自动装配

  • 只有在 foobar 配置文件处于活动状态时,FooBar bean 才会被注册

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 {
// ...
}
kotlin
备注

这个 DSL 是编程式的,这意味着它允许通过 if 表达式、for 循环或任何其他 Kotlin 构造来进行自定义的 bean 注册逻辑。

然后,您可以使用这个 beans() 函数在应用程序上下文中注册 bean,如下例所示:

val context = GenericApplicationContext().apply {
myBeans.initialize(this)
refresh()
}
kotlin
备注

Spring Boot 基于 JavaConfig,尚未提供对函数式 Bean 定义的特定支持,但您可以通过 Spring Boot 的 ApplicationContextInitializer 支持实验性地使用函数式 Bean 定义。有关更多详细信息和最新信息,请参阅此 Stack Overflow 答案。另请参阅在 Spring Fu incubator 中开发的实验性 Kofu DSL。