此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

Bean 定义 DSL

Spring Framework 支持使用 lambda 以功能方式注册 bean作为 XML 或 Java 配置的替代方案(@Configuration@Bean). 简而言之 它允许您使用 lambda 注册 bean,该 lambda 充当FactoryBean. 这种机制非常有效,因为它不需要任何反射或 CGLIB 代理。spring-doc.cadn.net.cn

例如,在 Java 中,您可以编写以下内容:spring-doc.cadn.net.cn

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 中,使用具体化的类型参数和GenericApplicationContextKotlin 扩展,您可以改为编写以下内容:spring-doc.cadn.net.cn

class Foo

class Bar(private val foo: Foo)

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

当班级Bar有一个构造函数,你甚至可以只指定 bean 类,构造函数参数将按类型自动连接:spring-doc.cadn.net.cn

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

为了允许更具声明性的方法和更简洁的语法,Spring Framework 提供了Kotlin bean 定义 DSL它声明了一个ApplicationContextInitializer通过干净的声明式 API,它允许您处理配置文件和Environment用于定制如何注册 bean。spring-doc.cadn.net.cn

在以下示例中,请注意:spring-doc.cadn.net.cn

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 是编程的,这意味着它允许 bean 的自定义注册逻辑通过if表达式,一个for循环或任何其他 Kotlin 构造。

然后您可以使用beans()函数在应用程序上下文上注册 bean,如以下示例所示:spring-doc.cadn.net.cn

val context = GenericApplicationContext().apply {
	myBeans.initialize(this)
	refresh()
}
Spring Boot 基于 JavaConfig,目前还没有提供对函数式 Bean 定义的具体支持,但您可以通过 Spring Boot 的ApplicationContextInitializer支持。 有关更多详细信息和最新信息,请参阅此 Stack Overflow 答案。另请参阅在 Spring Fu 孵化器中开发的实验性 Kofu DSL。