首页 > 解决方案 > 尝试使用构造函数调用类,但 @Autowired var 在 Kotlin/Spring Boot 中抛出空指针异常

问题描述

我是 Kotlin 和 Spring Boot 的新手。我正在尝试通过 ServiceClass 调用具有初始化构造函数的 SearchService 类,一切都很好,直到可以访问 SearchService 中的 Autowired env 变量 - 它抛出空指针异常。我假设我必须在 ServiceClass 中自动装配 SearchService,但是我将如何在 performSearch 方法中初始化构造函数和 name/isAlive 变量。

@Service
class ServiceClass {
    @Autowired
    lateinit var env: Environment

    fun performSearch(req: String): String {
        var searchService = SearchService("John", false)
        result = searchService.searchAsync()
            ...
        return result
    }
}

@Repository
class SearchService(name: String = "", isAlive: Boolean = true) {
    private var name: String = name
    private var isAlive: Boolean = isAlive

    @Autowired
    lateinit var env: Environment

    fun searchAsync(): String {
        var endpoint = env.getProperty("endpoint").toString() + name //Error here
        // makes call to get endpoint with Name and isAlive as params
            ...
        return result
    }
}

标签: springspring-bootkotlin

解决方案


你是对的,你也需要自动装配SearchService。Spring 只能将依赖项自动装配到它创建的组件中。因为您正在创建SearchService自己,所以 Spring 不知道它的存在,也不会自动装配到其中。

你的第二个问题是:如果你自动装配SearchService,你如何初始化它的其他属性,比如nameand isAlive?这是依赖注入的一个常见问题,当构造函数的一些参数是依赖项而其他参数是数据时,就会出现这种问题。

解决方案是使用工厂设计模式。在依赖注入中,有时也称为“辅助注入”。创建另一个“工厂”组件,其唯一工作就是SearchService为您创建:

@Component
class SearchServiceFactory(private val env: Environment) {
    fun createSearchService(name: String = "", isAlive: Boolean = true) = 
        SearchService(env, name, isAlive)
}

然后您应该从 中删除@Repository注释SearchService,因为它的创建不是由 Spring 直接管理的。

工厂可以在您需要使用的任何地方自动接线,然后Environment自动接线。当您想要创建 时SearchService,您调用createSearchService以提供附加数据参数的值。

您的服务类别将更改为以下内容:

@Service
class ServiceClass(private val factory: SearchServiceFactory) {
    fun performSearch(req: String): String {
        var searchService = factory.createSearchService("John", false)
        result = searchService.searchAsync()
            ...
        return result
    }
}

请注意,在示例中,我使用了构造函数注入而不是@Autowired. 在实例化 Kotlin 类时,Spring 将自动为构造函数参数提供值,就像它是一个自动装配的字段一样。使用构造函数注入而不是字段注入有助于确保在编译时检测到您遇到的问题,而不是在运行时导致空指针异常。


推荐阅读