首页 文章

Spring Proxy Class和Kotlin中的空指针异常

提问于
浏览
6

我和kotlin一起面临 Spring 天的问题 .

我有一个控制器bean(没有接口btw),它通过主构造函数有一个自动连接的服务bean .

除非我为控制器使用缓存注释,否则它完美地工作 . 显然,spring缓存会在引擎盖下生成一个代理类来处理缓存 .

我的代码如下所示:

@RestController
@RequestMapping("/regions/")
open class RegionController @Autowired constructor(val service: RegionService) {
    @RequestMapping("{id}", method = arrayOf(RequestMethod.GET))
    @Cacheable(cacheNames = arrayOf("regions"))
    fun get(@PathVariable id: Long): RegionResource {
        return this.service.get(id)
    }
}

现在的问题是在执行方法时出现空指针异常,实际上 this.servicenull ,这在技术上是不可能的,因为它是kotlin中的非空变量 .

我假设class proxies generated by spring用null值而不是autowired bean初始化类 . 这必须是使用kotlin和spring的常见陷阱 . 你是如何规避这个问题的?

2 回答

  • 9

    很快这可能不再是问题 .

    正在进行的工作中,任何lib(包括spring)都可以在META-INF中指定文件的注释列表 . 一旦使用其中一个类对其进行注释,它将默认为类本身及其所有函数打开 . 对于从带注释的类继承的类也是如此 .

    有关详细信息,请查看https://github.com/Kotlin/KEEP/pull/40#issuecomment-250773204

  • 1

    在Kotlin默认情况下都是classes and members are final .

    对于能够代理方法的代理库(CGLIBjavaassist),必须将其声明为 non final 并且在 non final 类(since those libraries implement proxying by subclassing)中 . 将您的控制器方法更改为:

    @RequestMapping("{id}", method = arrayOf(RequestMethod.GET))
    @Cacheable(cacheNames = arrayOf("regions"))
    open fun get(@PathVariable id: Long): RegionResource {
        return this.service.get(id)
    }
    

    您可能会在控制台中看到有关 RegionController 方法无法进行代理的警告 .

    Kotlin编译器插件

    Kotlin团队承认了这一困难并创建了一个插件,标志着标准的AOP代理候选者,例如: @Componentopen .

    您可以在 build.gradle 中启用插件:

    plugins {
      id "org.jetbrains.kotlin.plugin.spring" version "1.1.60"
    }
    

相关问题