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 社区的所有近期活动。

查看全部