当2月份JetBrains发布Kotlin这门JVM语言的时候,我就开始关注她了。她给我的第一印象就是语法简约又不简单。特别是写久了啰嗦臃肿的Java以后,再接触这样的语言,确实让能让我眼前一亮。然而由于工作原因,我没有太多时间去专门学习她,也是一大遗憾。好在现在要写一个Telegram机器人,自然而然想到的就是用Kotlin来写了,同时希望使用上高度自动配置化的Spring Boot框架,所以简单总结了一下Spring Boot和Kotlin一起开发的几个注意点。

Kotlin能与Spring Boot一起工作吗?

JetBrains表示Kotlin可以与Java做到100%的兼容,Kotlin官方Tutorials上也有Spring Boot与Kotlin一起编写RESTful服务的例子,所以Kotlin是可以和Spring Boot一起工作的。

Spring Boot启动类

在Java中,启动Spring Boot需要有一个加上了 @SpringBootApplication 注解的类,类里面还要有一个 public static void main(String[] args) 方法。在Kotlin中没有 static 这个关键字,但是可以用 companion objects 来代替。所以在Kotlin中,Spring Boot的启动类可以这样来写:

1
2
3
4
5
6
7
8
9
10
11
@SpringBootApplication
open class App {

companion object {
@JvmStatic
fun main(args: Array<String>) {
SpringApplication.run(App::class.java, *args)
}
}

}

需要注意的是,启动类要是 open 的,并且在main方法上要加上 @JvmStatic 注解。

依赖注入

在Java中,Spring的依赖注入可以有fields、constructor和setters三种方式,在Kotlin中也一样。

  • 域注入相对简单, 需要注意的是,在Kotlin中域注入需要使用 lateinit 关键字:

    1
    2
    3
    4
    class SampleController {
    @Autowired lateinit var sampleService: SampleService
    // ...
    }
  • 构造方法注入需要使用Kotlin的主构造方法完成:

    1
    2
    3
    class SampleController @Autowired constructor(val sampleService: SampleService) {
    // ...
    }
  • Setter方式注入在Kotlin中的语法如下:

    1
    2
    3
    4
    5
    class SampleController {
    lateinit var sampleService: SampleService
    @Autowired set
    // ...
    }

初始化Logger

Spring Boot默认的日志实现方案是 slf4j + logback,初始化Logger需要使用 LoggerFactory.getLogger(Class<?> clazz) 。在Kotlin中获得一个Java类对象需要用到 ::class.java ,语法如下:

1
val logger = LoggerFactory.getLogger(SampleController::class.java)

Jackson反序列化

Spring Boot使用Jackson来处理Java对象与Json的序列化和反序列化。在Kotlin中,Jackson序列化可以正常工作,但是反序列化需要引入 Jackson Kotlin Module 。 除了要在build.gradle中引入依赖外, 还需要将 KotlinModule 注册成一个Bean:

1
2
3
4
5
6
7
@SpringBootApplication
open class App {

@Bean
open fun kotlinModule() = KotlinModule()

}

参考文章: