从Java 8到Kotlin的Spring Boot应用程序之旅

Categories:   
Spring Boot     
Kotlin    

从Java 8到Kotlin的Spring Boot应用程序之旅

在写了很多年的Ruby / Rails之后,最近我发现自己写了大量的Spring Boot应用程序。
Spring Boot JVM的一个很好的框架,它通过“使创建“可以轻松运行”的独立的,生产级的基于Spring的应用程序变得容易”来关注开发人员的工作效率。它具有许多Rails的感觉。“常规配置”部门,但是由于我最终使用Java 8,因此我失去了用Ruby编写时获得的“乐趣”。尽管Java 8在Java 7方面进行了重大改进,但我还是想知道通过使用
Kotlin
编写Spring Boot应用程序
,我可以获得更多的喜悦

Kotlin是
JetBrains的
一种新语言,它
是IntelliJ和RubyMine的创建者,可以代替Java开发其产品
他们的目标是创建一种更加简洁的基于JVM的语言,该语言有助于提高开发人员的工作效率,避免Java开发中的一些常见陷阱并与现有Java程序100%兼容。
它以Java 6为基准,同时仍添加了一些出色的语言功能,因此对Android开发也非常有用。

这篇文章以及所有后续文章将以现有的Java 8 / Spring Boot 
应用程序
作为探索的起点。
这将使我看到Java 8语法和Kotlin语法之间的直接比较。
这次旅行将使我能够亲身体验Spring Boot / Kotlin应用程序的外观,并在学习过程中学习比“ Hello World”应用程序还多的语言。
如果您想在旅途中继续前进,可以在

GitHub上查看
不断发展的源代码


此外,这些帖子并不意味着要成为有关Kotlin的完整教程,而仅涵盖与转换有关的语言功能。
如果您需要完整的教程,则Kotlin网站上有很多

很好的信息

最后,如果您
对代码
有任何改进建议
,请随时提交GitHub问题或提交拉取请求。

起跑线


启动Spring Boot应用程序时,我们需要的第一件事是应用程序类。
这是
我开始


应用程序类

package com.example.billing;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker

public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

...

这里没有惊喜。
main()

当您运行可执行jar文件时,我们在Spring Boot检测到的Application类上
创建一个静态
方法。

这是Kotlin中的同一应用程序类:

package com.example.billing

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker
import org.springframework.cloud.client.discovery.EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker

// This class must not be final or Spring Boot is not happy.
open class Application {
    companion object {
        @JvmStatic fun main(args: Array<String>) {
            SpringApplication.run(Application::class.java, *args)
        }
    }
}

您可能会注意到的第一个区别是缺少分号。
是的,女士们先生们,在科特林没有分号。
尽管对某些人来说不是什么大不了的事,但这对我来说是朝正确方向迈出的一步。

我注意到的下一个区别是
open

类定义前面

关键字。
默认情况下,Kotlin中的类是最终类,这是根据

Effective Java
继承的设计和文档中的

第17项,

否则将禁止使用


这是我第一次在Kotlin的“强制执行良好做法”与Spring Boot的约定之间产生摩擦。


@SpringBootApplication
是一个方便的注释,标记与类
@Configuration

@EnableAutoConfiguration

@ComponentScan

注释。
正是

@Configuration
注解强制使用
open
关键字。
open

在应用程序启动时,
删除
关键字会导致运行时错误:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: @Configuration class 'Application' may not be final. Remove the final modifier to continue.


由于此应用程序类不包含任何配置信息,因此修复起来很容易。
而不是使用的

@SpringBootApplication
标注可以
替代
@EnableAutoConfiguration

@ComponentScan
注释。

package com.example.billing

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker
import org.springframework.cloud.client.discovery.EnableDiscoveryClient

@EnableAutoConfiguration
@ComponentScan
@EnableDiscoveryClient
@EnableCircuitBreaker

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

我注意到的最终差异在于
main()

方法
的定义

Kotlin有一个

伴随对象
的想法

这些对象的使用方式类似于Java中的静态方法,但不完全相同。
这就是

@JvmStatic

注释的来源。该注释告诉Kotlin生成实际的Java静态方法,而不是Kotlin中默认的“ kinda,sorta”方法。
此注释是对JVM兼容性进行投资的一个很好的例子。


main()
方法也缺少
public
修饰符。
默认情况下

方法
在Kotlin中
是公共的
,这减少了Java应用程序中存在的样板。

最后,您会注意到Kotlin中的数组是实际的参数化类,而不是Java中的原始类型。
Kotlin还在变量定义后放置类型注释。
我们将在以后的帖子中探讨为什么这很重要。

Kotlin应用程序类的最后一个难题是,您必须告诉Spring Boot在哪里可以找到应用程序类。
在Gradle中,就像这样简单:

springBoot {
    mainClass = 'com.example.billing.Application'
}

备用应用程序类

Kotlin还允许在类之外定义函数,因此我们可以将应用程序类重写为:

package com.example.billing

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
import org.springframework.context.annotation.ComponentScan

@EnableAutoConfiguration
@ComponentScan
@EnableDiscoveryClient
@EnableCircuitBreaker

class Application

fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}

如果执行此操作,则该
main()
方法在名为的类上定义,该类
ApplicationKt
以file命名
Application.kt
,这会稍微改变
build.gradle
条目:

springBoot {
mainClass = 'com.example.billing.ApplicationKt'
}

此定义
main()

稍微
简化了
方法
的签名

注释和显式的伴随对象已经一去不复返了,因此代码也变得更加整洁。


我不确定我更喜欢哪一个。
使用伴随对象可以更明确地说明哪个类包含该

main()

方法,但是上面的定义更为简洁。
在这里,我们以较少的代码交换来隐式理解编译器将生成ApplicationKt类。
随着时间的流逝,我认为简化的应用程序类将在我身上发展。

总结思想


从Java 8到Kotlin的Spring Boot应用程序之旅

在我看来,Kotlin作为“更好的Java”朝正确的方向迈出了一步。
在我看来,语言设计师已尽其所能保持与现有Java程序的兼容性,同时又不受Java遗留的束缚。
缺少半冒号似乎是微不足道的,但会在大型代码库中加起来,并且在语言级别实施最佳实践也将有助于大型代码库。

是的,在平稳地与Spring Boot集成方面存在一些小难题,但是新语法和语言结构的好处远远超过了这些难题。

在我们
在下一篇文章中

,我们将看看Java的 Spring Boot
配置类,并将它们与自己的兄弟科特林。

希望我们将继续看到Kotlin带来的收益将超过Spring Boot带来的摩擦。



本系列


第一篇文章
中,我们研究了Spring Boot应用程序类从Java 8到Kotlin的转换。
这些迁移的好处是,由于Kotlin与旧版Java的结合很好,因此可以逐步完成它们。
实际上,这是该语言的设计考虑因素之一。

在第二篇文章中,我们将研究配置类到Kotlin的转换。

这是用Java 8编写的Spring Boot配置类的示例:

package com.example.billing;

import com.example.billing.reocurringPayments.Service;
import com.example.payments.RecurlyGateway;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class Configuration {
    @Bean
    public com.example.payments.Gateway paymentGateway() {
        return new RecurlyGateway();
    }

    @Bean
    public Service serviceThatMayFail() {
        return new Service();
    }
}

这是用Kotlin编写的同一配置类:

package com.example.billing

import com.example.billing.reocurringPayments.Service
import com.example.payments.RecurlyGateway
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
open class Configuration {
    @Bean
    open fun paymentGateway() = RecurlyGateway()

    @Bean
    open fun serviceThatMayFail() = Service()
}

没有很多巨大的差异,但以下是一些对我来说比较小的差异:


  • 必须将Configuration类声明为打开。
    这是因为Spring Boot继承了您的配置类,但是Kotlin默认将它们定型为final。
    有关
    详情,
    请参见

    此处

  • 出于与上述相同的原因,必须声明@Bean函数为打开状态。

  • 函数上没有返回类型,因为Kotlin会推断这些类型。
    这种类型推断是Kotlin我最喜欢的功能之一。

  • Kotlin对于
    单表达式函数
    具有隐式返回(且没有花括号)

    当函数主体中只有一个表达式时,Kotlin会自动假定您要返回该值,因此不需要显式

    return

    或大括号。
    对于具有多个表达式的主体,

    return
    仍然是必需的,因为编译器可能无法猜测函数的返回类型。

  • new

    初始化对象时
    没有
    关键字。
    再加上类型推断,隐式返回和单条语句/不使用大括号,就构成了一个不错的紧凑型配置类。

在Kotlin中,Spring配置类对我来说是个好主意。
实际的代码差异只有4行代码(18对14),但是在Kotlin中,视觉噪声大大降低了。
对于我来说,必须将类和所有方法都声明为开放似乎有点笨拙,但由于类型推断,单表达式函数没有返回值以及这些类从Kotlin获得的其他改进,我愿意忽略它。


谢谢阅读。
在我们

在下一篇文章中 ,我们将看看使用科特林的数据类实现的POJO。

欢迎使用我们的Java 8-> Kotlin转换的第三部分,用于Spring Boot应用程序。
上次 我们看到将配置类转换为Kotlin如何帮助清除Java中所需的一些样板代码。

在第三部分中,我们将继续我们的主题“用Kotlin编写更少的代码”,并研究
Kotlin数据类
如何
帮助我们清理POJO数据类。

我们的
起点 是一个普通的旧Java对象(POJO),用于保存一些通过RabbitMQ发送的数据:

package com.example.email;

import java.io.Serializable;

public class EmailMessage implements Serializable {

    private final String toAddress;
    private final String subject;
    private final String body;

    public EmailMessage(String toAddress, String subject, String body) {
        this.toAddress = toAddress;
        this.subject = subject;
        this.body = body;
    }

    public String getToAddress() {
        return toAddress;
    }

    public String getSubject() {
        return subject;
    }

    public String getBody() {
        return body;
    }
}

下面是
同一类 的实现
科特林数据类

package com.example.email

import java.io.Serializable

data class EmailMessage(val toAddress: String, val subject: String, val body: String) : Serializable

该代码不仅比Java代码短得多,而且具有更多功能。
作为Kotlin数据类,此少量代码将获得:

  • 生成一
    equals()/hashCode()

    对的
    实现

  • 默认
    toString()
    方法

  • 一种
    copy()
    允许轻松更改对象的各个属性的方法

  • 在赋值语句中
    分解
    对象
    的能力

JSON反序列化
Spring Data JPA
可以方便地使用此功能

当有人评估从Java到Kotlin的转换时,这些数据类是在Spring Boot应用程序中采用Kotlin的主要原因。
它们可以帮助您编写并维护更少的代码,而我想维护的代码也越少越好。

https://engineering.pivotal.io/post/spring-boot-application-with-kotlin/

原文 

http://mp.weixin.qq.com/s?__biz=MzA5OTI2MTE3NA==&mid=2658338469&idx=5&sn=7f9f6f7c46aad32aac355394ae1b58cb

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 从Java 8到Kotlin的Spring Boot应用程序之旅

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址