【问题标题】:Kotlin with Spring DI: lateinit property has not been initialized带有 Spring DI 的 Kotlin:lateinit 属性尚未初始化
【发布时间】:2017-11-09 14:45:14
【问题描述】:

我没有在 Kotlin 中获得基于 Spring 的 setter 依赖注入工作,因为它总是以错误消息“lateinit property api has not been initialized”终止。我可以将问题简化为以下场景:有一个接口

interface IApi {
  fun retrieveContent(): String
}

实现
class Api : IApi {
    override fun retrieveContent() = "Some Content"
}

我想在另一个应该发生依赖注入的类中使用实现:

@Component
class SomeController {
    @Autowired lateinit var api: IApi
    fun printReceivedContent() {
        print(api.retrieveContent())
    }
}

但是,应用程序终止并显示上述错误消息。我的 Spring 配置如下所示:

@Configuration
open class DIConfig {
    @Bean
    open fun getApiInstance(): IApi = Api()
}

在主函数中,我加载应用程序上下文并调用方法:

fun main(args: Array<String>) {
    val context = AnnotationConfigApplicationContext()
    context.register(DIConfig::class.java)
    context.refresh()

    val controller = SomeController()
    controller.printReceivedContent()
}

这里有什么问题?

【问题讨论】:

    标签: spring dependency-injection kotlin kotlin-lateinit


    【解决方案1】:

    如果您只是像这样自己调用构造函数,则不涉及 Spring。和Java一样,

    val controller = context.getBean(SomeController::class.java)
    

    Spring Framework 5.0 增加了Kotlin extensions,所以你也可以写其中一个

    val controller = context.getBean<SomeController>()
    val controller: SomeController = context.getBean()
    

    【讨论】:

    • 谢谢!您描述的方式有效。但是,在配置文件中,我需要添加以下 bean 定义:@Bean open fun getSomeController() = SomeController() 有没有办法省略这个“不必要的”代码?
    【解决方案2】:

    你的 api 目前不是 spring 管理的 bean,尝试用 @Service 或 @Component 注解它

    【讨论】:

      【解决方案3】:

      @Autowired 通常被添加到属性的设置器中。因此,不要将其用于属性,而应显式注释设置器:

      @set:Autowired lateinit var api: IApi
      

      【讨论】:

      • 不幸的是,这不起作用。像 lateinit var api: IApi @Autowired set 这样显式注释 setter 也不起作用。
      猜你喜欢
      • 2018-11-06
      • 2019-12-15
      • 1970-01-01
      • 2020-09-23
      • 2019-12-02
      • 2021-06-21
      • 2017-03-03
      • 2012-05-26
      • 1970-01-01
      相关资源
      最近更新 更多