Spring Fu 的演進

工程 | Sébastien Deleuze | 2018 年 10 月 02 日 | ...

我借在 SpringOne platform(我在那裡首次發表了關於 Spring Fu 的演講)和 Kotlinconf 之間的短暫停留機會,概述一下這個專案的演進,總結當前狀態,並分享接下來的可能步驟。

六月初,我宣佈了一個新的實驗性專案,命名為 Spring Fu,目標是嘗試使用 Kotlin DSL 和函式式配置來配置 Spring 應用程式的新型 API。

我必須承認,我沒有預料到隨之而來的巨大反饋浪潮,我要感謝 Spring 社群的熱烈歡迎。自那時以來,我一直在繼續研究該專案,以便將這個基於原始 Spring Framework API 的第一個概念驗證(POC)轉變為新的 Spring 函式式特性的孵化器。

Kofu 配置

Kotlin DSL 現在基於 Spring Boot 基礎設施,被稱為 Kofu(取自 Kotlin 和 functional)。它允許使用 Kotlin DSL 和 Lambda 配置 Spring Boot 應用程式,而不是使用註解,並具有以下特點:

  • 透過 Kotlin DSL 進行顯式配置
  • 基於以函式式方式使用的 Spring Boot 基礎設施
  • 不基於 classpath 檢測啟用功能
  • 既是宣告式的也是程式設計式的
  • 更快的啟動速度和更低的記憶體消耗
  • 最少的反射和註解使用
  • 純 Lambda,無 CGLIB 代理

使用 Kofu 配置的典型 Spring Boot 應用程式如下所示

val app = application {
  import(beans)
  listener<ApplicationReadyEvent> {
    ref<UserRepository>().init()
  }
  properties<SampleProperties>("sample")
  server {
    port = if (profiles.contains("test")) 8181 else 8080
    mustache()
    codecs {
      string()
      jackson {
        indentOutput = true
      }
    }
    import(::routes)
  }
  mongodb {
    embedded()
  }
}

val beans = beans {
  bean<UserRepository>()
  bean<UserHandler>()
}

fun routes(userHandler: UserHandler) = router {
  GET("/", userHandler::listView)
  GET("/api/user", userHandler::listApi)
  GET("/conf", userHandler::conf)
}

fun main() = app.run()

要使用它,您“只需”向 Spring Boot 2.1 應用程式新增一個 org.springframework.fu:spring-boot-kofu 依賴項。當前的版本號 0.0.2 表明,請注意,目前的 API 尚不穩定,不適合生產環境,並且範圍僅限於 Spring Boot 支援的子集。

但請隨意試用,傳送反饋,並嘗試這種配置 Spring Boot 應用程式的新方法,它是函式式的,可透過您的 IDE 自動完成來發現,並且有文件

Kofu 與自動配置無優劣之分,只是方式不同。我相信它可以成為 Spring Boot 吸引那些偏愛更顯式配置模型的開發者以及來自 Kotlin、Go、Node 或 Ruby 等其他背景開發者的途徑。

Jafu 配置

最初僅限於 Kotlin,我收到的主要反饋之一來自對這種顯式 DSL 方法感興趣的 Java 開發者,所以我著手開發了對應的 Java 版本,最終形成了這個 Jafu(取自 Java 和 functional)DSL。

public class JafuApplication {

  public static SpringApplication app = application(app -> {
    app.beans(beans -> {
      beans.bean(SampleService.class);
      beans.bean(SampleHandler.class);
    });
    app.server(server -> server.router(router -> {
      SampleHandler sampleHandler = app.ref(SampleHandler.class);
      router.GET("/", sampleHandler::hello);
      router.resources("/**", new ClassPathResource("static/"));
    }));
  });

  public static void main (String[] args) {
    app.run(args);
  }
}

這目前只是一個概念驗證(POC),但我計劃很快實現與 Kofu 的功能對等,並並行開發這兩種 DSL。缺乏型別安全的構建器具體化型別引數擴充套件機制將使 Jafu 比 Kofu 更冗長且可擴充套件性更差,但儘管有這些限制,我發現 Jafu 相當不錯且可用。

對於那些只對使用函式式 bean 註冊基礎設施帶來的效能提升感興趣的使用者,值得注意的是 Dave Syer 目前正在實驗一些解決方案,這些解決方案使得基於註解的常規 Spring Boot 應用程式能夠利用函式式 bean 註冊的效率。

將 Spring 應用程式作為原生可執行檔案執行

GraalVM 是 Oracle 開發的一種新的虛擬機器,除其他功能外,它可以透過 Substratevm 將 JVM 位元組碼編譯為原生可執行檔案。

Spring Framework 5.1 為 GraalVM 原生映象提供了一些初步支援,但這只是故事的開始。GraalVM 團隊需要修復 Dave 提出的一些問題,才能使一切按預期工作,並且生態系統需要適應這個具有不同約束和特性的新平臺。

但 GraalVM 團隊正在傾聽我們的反饋,並且 Spring 應用程式的支援在最近幾個月取得了顯著進展。現在已經可以將使用 Kofu 配置的基本 Spring Boot 響應式應用程式編譯為原生可執行檔案,並且幾乎瞬間執行!

協程支援

如前所述,Spring Fu 的主要目標是孵化將整合到當前頂級專案(如 Spring Framework、Spring Data 和 Spring Boot)中的功能。

Spring Fu 目前正在孵化對 Spring WebFlux 和 Spring Data 的協程支援,以便能夠以更命令式的方式利用 Spring 響應式堆疊。這主要面向那些希望利用此類堆疊的可擴充套件性而無需完全掌握響應式 API 強大功能的開發者。

class UserRepository(private val mongo: CoroutinesMongoTemplate) {
	suspend fun count(): Long = mongo.count<User>()
	suspend fun findAll(): List<User> = mongo.findAll<User>()
	suspend fun findOne(id: String): User? = mongo.findById<User>(id)
	suspend fun deleteAll() = mongo.remove<User>()
	suspend fun save(user: User): User? = mongo.save(user)
}

請注意,雖然協程在 Kotlin 1.3 中被視為最終版本,但 kotlinx-coroutines 中仍然缺少一個重要部分,因為它沒有提供任何型別來處理冷流。我們將需要這個缺失的抽象,以便能夠使用協程 API 暴露我們的響應式基礎,更多詳情請參見 kotlinx.coroutines#254

請注意,我們應該能夠在協程和 Reactor 型別之間傳遞上下文,以便實現響應式安全和事務等非常強大的用例。

透過他出色的 spring-kotlin-coroutine 專案貢獻了最初 Spring 協程支援的 Konrad Kaminski 將很快加入 Spring Fu 與我一起開發此功能。

結論

我剛剛釋出了 Spring Fu 0.0.2,它提供了改進的 Kofu DSL 並引入了函式引數自動注入。請隨意嘗試並提供反饋。

即將釋出的 Spring Fu 0.0.3 將在 Kofu 和 Jafu 配置之間提供功能對等。

我們已經有 10 多位社群貢獻者向 Spring Fu 提交了 Pull Request,所以如果您有一些想法,您也許就是下一個 ;-)

期待在即將到來的 Spring Fu 演講中與您見面,地點包括 JFuture (明斯克)、Spring Fest (東京) 和 Devoxx (安特衛普)。

訂閱 Spring 電子報

訂閱 Spring 電子報,保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您快速提升。

瞭解更多

獲取支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

近期活動

檢視 Spring 社群的所有近期活動。

檢視全部