【问题标题】:Trying to call a class with constructor but @Autowired var is throwing Null Pointer Exception in Kotlin/Spring Boot尝试使用构造函数调用类,但 @Autowired var 在 Kotlin/Spring Boot 中抛出空指针异常
【发布时间】:2021-10-07 00:19:28
【问题描述】:

我是 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
    }
}

【问题讨论】:

    标签: spring spring-boot kotlin


    【解决方案1】:

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

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

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

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

    然后您应该从SearchService 中删除@Repository 注释,因为它的创建不是由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 将自动为构造函数参数提供值,就像它是一个自动装配的字段一样。使用构造函数注入而不是字段注入有助于确保在编译时检测到您遇到的问题,而不是在运行时导致空指针异常。

    【讨论】:

      猜你喜欢
      • 2015-08-10
      • 2021-08-31
      • 1970-01-01
      • 2017-07-02
      • 2019-05-11
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 2017-08-28
      相关资源
      最近更新 更多