领先一步
VMware 提供培训和认证,助您加速进步。
了解更多借着在 SpringOne platform(在此我做了关于Spring Fu的第一个演讲)和 Kotlinconf 之间的短暂间隙,我想对该项目的演进做一个概述,总结当前状态并分享下一步可能的计划。
六月初,我宣布了一个名为 Spring Fu 的新实验性项目,旨在通过Kotlin DSL和函数式配置来试验一种配置Spring应用程序的新型API。
今天,我自豪地宣布一个新实验性项目:Spring Fu。它是一个 @Kotlin 微框架,使我们能够使用函数式API而非注解来轻松创建轻量级的Spring驱动应用程序。我们正在寻求反馈。 https://#/R15wJ1gD8K pic.twitter.com/ScljoPZ8rW
— Sébastien Deleuze (@sdeleuze) 2018年6月8日
我必须承认,我没有预料到随之而来的巨大反馈浪潮,我想感谢Spring社区如此热烈的欢迎。此后,我继续致力于该项目,希望能将这个基于原生Spring Framework API的第一个POC转化为Spring新函数式功能的一个孵化器。
Kotlin DSL 现在基于Spring Boot基础设施,并称为Kofu(取自Kotlin和functional)。它允许使用Kotlin DSL和lambda而不是注解来配置Spring Boot应用程序,并具有以下特点:
使用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等其他背景的开发者的途径。
最初仅限于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。缺乏类型安全构建器、reified类型参数或扩展机制将使Jafu比Kofu更冗长且可扩展性更差,但尽管有这些限制,我认为Jafu仍然非常不错且可用。
对于仅对使用函数式Bean注册基础设施带来的性能提升感兴趣的用户,值得注意的是,Dave Syer目前正在试验一些解决方案,这些方案可以使我们能够利用函数式Bean注册的效率,同时仍使用基于注解的常规Spring Boot应用程序。
GraalVM是Oracle开发的一个新的虚拟机,它除了其他功能外,还可以通过Substratevm将JVM字节码编译为原生可执行文件。
Spring Framework 5.1为GraalVM原生镜像提供了一些初步支持,但我们仍处于故事的开端。GraalVM团队需要修复Dave提出的各种问题,才能让一切正常工作,而生态系统也需要适应这个拥有不同约束和特性的新平台。
但GraalVM团队正在倾听我们的反馈,Spring应用程序的支持在最近几个月取得了显著进展。现在已经可以编译一个基本的Spring Boot响应式应用程序(使用Kofu配置)作为原生可执行文件,它几乎可以瞬间启动!
我在杜勒斯机场玩spring-fu。
— Toshiaki Maki (@making) 2018年9月28日
看看它有多快!太疯狂了…… pic.twitter.com/CTyKEr4d4O
如前所述,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(安特卫普)。