【问题标题】:How to use "Functional bean definition Kotlin DSL" with Spring Boot and Spring WebFlux?如何在 Spring Boot 和 Spring WebFlux 中使用“功能 bean 定义 Kotlin DSL”?
【发布时间】:2018-02-06 17:20:56
【问题描述】:

https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/kotlin/org/springframework/context/support/BeanDefinitionDsl.kt 的评论显示了如何通过新的“功能 bean 定义 Kotlin DSL”来定义 Spring Bean。我还找到了https://github.com/sdeleuze/spring-kotlin-functional。但是,此示例仅使用 plain Spring 而不是 Spring Boot。任何关于如何将 DSL 与 Spring Boot 一起使用的提示都值得赞赏。

【问题讨论】:

  • 你有没有试过,例如通过将此 bean 定义放入控制器(由 spring boot 发现)?
  • 是的,我尝试了一个带有@Bean 方法的@Configuration 类,该方法返回beans {...} 的结果。然后,当我删除 @Service 并在上面的 beans {...} lambda 中声明服务类时,我得到了异常 "... No qualifying bean of type '...' available ..."

标签: spring spring-boot kotlin spring-webflux


【解决方案1】:

Spring Boot 基于 Java Config,但应允许通过 ApplicationContextInitializer 支持对用户定义的 functional bean declaration DSL 进行实验性支持,如 here 所述。

实际上,您应该能够在包含 beans() 函数的 Beans.kt 文件中声明您的 bean。

fun beans() = beans {
    // Define your bean with Kotlin DSL here
}

然后为了让Boot在运行main()和测试时考虑到它,创建一个ApplicationContextInitializer类如下:

class BeansInitializer : ApplicationContextInitializer<GenericApplicationContext> {

    override fun initialize(context: GenericApplicationContext) =
        beans().initialize(context)

}

最后,在你的 application.properties 文件中声明这个初始化器:

context.initializer.classes=com.example.BeansInitializer  

您将找到完整的示例 here,也可以关注 this issue,了解 Spring Boot 对功能性 bean 注册的支持。

【讨论】:

  • 关于您的答案的两个问题: * 测试设置将使用 SpringRunner 和 JUnit 来获取此初始化,对吗? * 是否有任何其他方法可以在不必创建properties 文件的情况下实现此行为,包括在测试中获取此初始化?谢谢!
  • 是,但还没有。
  • 旁注:我们目前正在github.com/spring-projects/spring-fu 孵化器项目中探索使用 Java 或 Kotlin DSL 的完整功能 bean 定义。
  • 如果我想覆盖一个bean怎么办?我添加了 allow-bean-definition-overriding: true 并试图通过 @Bean 声明一个测试 bean,但它似乎被忽略了。我在没有otu bean DSL的项目上尝试了完全相同的设置(基本上,只是复制粘贴)并且它有效。
  • 像这样声明初始化程序会禁用 Spring Boot 提供的所有其他初始化程序,不是吗?
【解决方案2】:

在 Spring Boot 中执行此操作的另一种方法是:

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args) {
        addInitializers(
                beans {
                    // Define your bean with Kotlin DSL here
                }
        )
    }
}

【讨论】:

  • 这种方法的缺点是初始化器不会被考虑到测试中。
【解决方案3】:

您可以在 *Config.kt 文件中定义您的 bean,并实现 ApplicationContextInitializer 接口的 initalize 方法。

override fun initialize(applicationContext: GenericApplicationContext) {
    ....
}

这里有一些 bean 定义。

bean<XServiceImpl>("xService")

bean("beanName") {
        BeanConstructor(ref("refBeanName"))
}

【讨论】:

    猜你喜欢
    • 2021-12-28
    • 2018-07-02
    • 1970-01-01
    • 2019-07-29
    • 2019-05-25
    • 2018-11-08
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    相关资源
    最近更新 更多