在Spring Framework 5.0中引入Kotlin支持
我們幾個月前有介紹關于 Kotlin在start.spring.io上的支持 ,我們有一直在進行工作,以確保Spring和 Kotlin 在一起玩得很好。 Kotlin的一個關鍵優勢是它提供了一個與用Java編寫的庫之間非常好的 互操作性 。但是有更多的方法可以進一步,允許編寫完全成熟的Kotlin代碼,當開發您的下一個Spring應用程序。除了Spring Framework對Java 8的支持,Kotlin應用程序可以利用類似功能的Web或bean注冊API,還有其他Kotlin專用功能,應該可以讓你的生產力水平達到一個新的高度。
這就是為什么我們在 Spring Framework 5.0 M4 中引入了一個專門的Kotlin支持,我想在這篇博客中總結的功能,旨在使您的開發人員體驗無縫的在Spring中一起使用這些技術。你可以使用 這個鏈接 在Spring Framework bug tracker中查找Kotlin的相關問題。
利用Kotlin可空信息(nullable information)
Spring最初基于來自 Raman Gupta 的社區貢獻,現在利用 Kotlin null-safety support 以確定是否需要HTTP參數,而不必顯式地定義 required 屬性。 這意味著 @RequestParam name:String? 被視為不需要(not required), @RequestParam name:String 視為必需。 這也支持Spring消息 @Header 注解。
以類似的方式,使用 @Autowired 或 @Inject 的Spring bean注入使用此信息來知道是否需要bean。 @Autowired lateinit var foo:Foo 意味著 Foo 類型的bean必須在應用程序上下文中注冊,而 @Autowired lateinit var foo:Foo? 不會引發錯誤,如果這樣的bean不存在。
RestTemplate和Functional Web API的擴展
Kotlin extensions 允許以非侵入方式擴展現有的API,提供了一個更好的替代實用程序類或在Kotlin特定類層次結構中添加Kotlin專用功能到Spring中。一些類似 Mario Arias 的 KotlinPrimavera 已經展示了我們可以帶給Spring的各種Kotlin助手API,以允許編寫更多的慣用代碼。使用Spring Framework 5,我們集成了Spring框架中最有用和最受歡迎的擴展,并添加了新的擴展。
例如, Kotlin reified type parameters 為JVM泛型類型擦除提供了一個解決方法,因此我們介紹了一些擴展,以利用此功能在可能的情況下提供更好的API。
這允許為RestTemplate提供方便的API(感謝來自Netflix的 Jon Schneider 為此做出貢獻)。例如,要在Java中檢索“Foo”對象的列表,必須寫:
List<Foo> result = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<Foo>>() { }).getBody();
或者,如果你使用中間數組:
List<Foo> result = Arrays.asList(restTemplate.getForObject(url, Foo[].class));
而在Kotlin與Spring Framework 5擴展中,你將能夠寫:
val result : List<Foo> = restTemplate.getForObject(url)
請注意,Kotlin擴展名是靜態解析的,你必須導入它們。 在上面的示例中,您需要添加 import org.springframework.web.client.RestOperationsExtension.getForObject 才能使用它。 Kotlin擴展通常由IDE(如IntelliJ IDEA)(如靜態導入)自動建議,但對于嵌套在容器 object 中的擴展,它仍然無效(您可以投票KT-15440),所以直到它被修復,你將不得不手動添加Spring Kotlin擴展導入。
Spring Framework 5.0 M4中目前可用的“RestTemplate”或功能性Web API擴展包括:
- RestOperationsExtension
- ServerRequestExtension
- BodyInsertersExtension
- BodyExtractorsExtension
- ClientResponseExtension
這些擴展還提供了支持本地Kotlin KClass 的成員函數,允許你指定 Foo :: class 參數而不是 Foo :: class.java 。
Reactor Kotlin extensions
Reactor 是Spring Framework 5.0的反應基礎,并且有很好的機會你將使用它的 Mono , Flux 和[StepVerifier] 開發reactive Web應用程序時的API。
所以今天我們還通過新的 reactor-kotlin 項目在Reactor中引入Kotlin支持!它提供了擴展,能夠通過寫入 foo.toMono() 從任何類實例創建 Mono 實例,許多人喜歡 Mono.just(foo) 。它還支持例如使用 stream.toFlux() 從Java 8 Stream 實例創建 Flux 。還提供了 Iterable , CompletableFuture 和 Throwable 擴展以及基于KClass的Reactor API變體。
這仍然是這個項目的早期,所以如果你想提供沒有的功能,隨時自由地 貢獻 你自己的擴展。
Functional bean registration with Kotlin
Spring Framework 5.0引入了一種新的方式來注冊bean,使用lambda作為XML或JavaConfig的替代,使用 @Configuration 和 @Bean 。 簡而言之,它使得有可能注冊bean與一個 Supplier lambda,充當一個 FactoryBean 。
在Java中,你將會寫如下的代碼:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.registerBean(Foo.class);
context.registerBean(Bar.class, () -> new
Bar(context.getBean(Foo.class))
);
而在Kotlin中,reified類型參數允許我們簡單地寫:
val context = AnnotationConfigApplicationContext()
context.registerBean(Foo::class)
context.registerBean(Supplier {
Bar(context.getBean(Foo::class))
})
你可以看到Spring應用程序的一個具體例子,在 https://github.com/mix-it/mixit / 使用函數 web 和 bean注冊 API。
ApplicationContext 相關Kotlin可用擴展如下:
No need to declare your bean class as open anymore
直到現在,使用Kotlin構建Spring Boot應用程序時遇到的幾個問題之一是需要在每個類上添加一個 open 關鍵字,并且使用CGLIB(如 @Configuration 類)來代替Spring bean的成員函數。 這個需求的根本原因來自于事實,在Kotlin, classes are final by default 。
幸運的是,Kotlin 1.0.6現在提供了一個 kotlin-spring 插件,在默認情況下打開類和它們的成員函數,注解或元注解使用以下注解之一:
- @Component
- @Async
- @Transactional
- @Cacheable
元注解支持意味著用 @Configuration , @Controller , @RestController , @Service 或 @Repository 注解的類會自動打開,因為這些注解是使用 @Component 進行的元注解。
我們更新了 start.spring.io 默認啟用它。 你可以看看 這個Kotlin 1.0.6博客帖子 了解更多詳情,包括 新的 kotlin-jpa 和 kotlin-noarg 插件對Spring Data實體非常有用。
Kotlin based Gradle build configuration
回到5月,Gradle 宣布 ,他們將支持在Groovy之外的Kotlin中編寫構建和配置文件。這使得可以在IDE中具有完全自動完成和驗證,因為這些文件是常規靜態類型的Kotlin腳本文件。這很可能成為基于Kotlin的項目的自然選擇,但這也對Java項目也很有價值。
自5月以來, gradle-script-kotlin 項目不斷發展,現在可以使用2個警告:
- 你需要Kotlin 1.1-EAP IDEA插件來獲得自動完成(但如果你使用 kotlin-spring 插件,因為 1.1-M04 不能可靠地使用這個插件,等待Kotlin 1.1-M05 )
- 文檔不完整,但Gradle團隊對Kotlin Slack的#gradle頻道非常有幫助。
兩個 spring-boot-kotlin-demo 項目使用這種基于Kotlin的Gradle構建,可以隨意看看。我們)在start.spring.io 討論 上添加了這樣的支持。
Kotlin Script based templates
從4.3版本開始,Spring Framework提供了一個 ScriptTemplateView 使用支持 JSR-223 的腳本引擎來渲染模板。 K
這使得出現了一些有趣的使用情況,如使用 kotlinx.html DSL或簡單的Kotlin multiline(多線)’String’插值,編寫類型安全模板,例如此 kotlin -script-templating 項目。 這可以允許您在IDE中編寫具有完全自動完成功能和重構支持的這類模板:
import io.spring.demo.User
import io.spring.demo.joinToLine
"""
${include("header", bindings)}
<h1>Title : $title</h1>
<ul>
${(users as List<User>).joinToLine{ "<li>User ${it.firstname} ${it.lastname}</li>" }}
</ul>
${include("footer")}
"""
這個功能仍在進行中,但我正在與Kotlin團隊合作,暫時使其準備好對Spring Framework 5.0 GA上的嵌套模板和i18n在MVC和Reactive兩方面的支持。
結語
我使用Kotlin編寫Spring Boot應用程序越多,我覺得這兩種技術有著共同的目標,允許您使用表達性,簡短和可讀的代碼來更高效地編寫應用程序,而Spring Framework 5 Kotlin支持將這些技術以更加自然,簡單和強大的方式來展現給我們。
Kotlin可以用來編寫 基于注解的Spring Boot應用程序 ,但作為一種新的 functional and reactive applications 也將是一種很好的嘗試,Spring Framework 5.0將會啟用。
Kotlin團隊做了一個偉大的工作,修復幾乎所有的bug點,我們報告,所以非常感謝他們。即將到來的Kotlin 1.1版本預計也修復 KT-11235 ,以允許指定數組注解標記單個屬性值,無須使用 arrayOf() 。你將面臨的主要問題可能是 KT-14984 ,它將需要明確指定lambda類型(如 Supplier {} 或 HandlerFunction {} )其中只需指定 {} 應該就足夠了。
通過轉到 start.spring.io 并生成一個Spring Boot 2.0.0(SNAPSHOT) 項目,可以自由測試Spring Framework 5.0 Kotlin支持并在這里或者在 Kotlin Slack 的“#spring”頻道向我們發送您的反饋。你也可以 貢獻 你需要的Kotlin擴展;-)
來自:https://muyinchen.github.io/2017/01/09/在Spring Framework 5.0中引入Kotlin支持/