介绍 Spring Scala

工程 | Arjen Poutsma | 2012年12月10日 | ...

去年十月,在 SpringOne2GX 大会上,我向全世界介绍了 Spring Scala 项目。此后,我还在 Devoxx 上介绍了这个项目。在这篇博文中,我想进一步详细介绍这个项目以及如何在您的 Scala 项目中使用它。

为什么选择 Spring Scala?

Spring Scala 项目的目标很简单:让在 Scala 中使用 Spring 框架变得更容易。我们相信有许多 Spring 用户想要尝试 Scala,但又不想放弃他们使用 Spring 的经验。这个项目就是为这些人准备的。

显然,您今天可以在 Scala 中使用 (Java) Spring Framework,而无需 Spring Scala。但这样做在某些地方会很尴尬。就像任何编程语言一样,Scala 有自己独特的方式,在 Scala 中使用像 Spring 这样的纯 Java 框架会让人感觉“太 Java 味”。Spring Scala 试图通过让 Spring 成为 Scala 语言的一等公民来解决这个问题。

Spring Scala 概述

Spring Scala 仍在开发中。在这篇文章的其余部分,我将重点介绍当前已实现的功能。但是,我们预计在未来几个月内会增加许多额外功能,希望通过您提供的反馈来实现。因此,如果您对某个功能有想法,能让 Spring 在 Scala 中使用起来更愉快,请通过提交 JIRA issue 或留言告诉我们。

在 XML 中装配 Bean

在 Spring XML 应用程序上下文中装配 Scala Bean 最简单和首选的方法是使用构造函数注入。例如,假设我们有以下 Scala 类


class Person(val firstName: String, val lastName: String)

您可以像这样使用 c 命名空间装配这个类


<bean id="person" class="Person" c:firstName="John" c:lastName="Doe"/>

请注意,通过将构造函数注入与 val 结合使用,我们还使 Person 类成为不可变的。函数式语言,如 Scala,鼓励不可变数据结构。因此,在 Scala 中使用 Spring 时,首选构造函数注入。另请注意,构造函数注入开箱即用;您无需在类路径中包含 Spring Scala jar 即可使其工作。

当涉及到 Setter 注入时,事情变得有点复杂。默认情况下,Scala 类不遵循 JavaBeans 属性契约(例如 String getFoo()void setFoo(String))。相反,Scala 有自己的属性契约:“getter”不以 get 为前缀,而是使用字段名作为方法名(例如 foo: String)。Scala setter 将字段名后缀为 = (例如foo=(String): Unit)。

为了解决这个问题,您可以指示 Scala 编译器通过使用 @scala.reflect.BeanProperty 注解来生成 JavaBeans getter 和 setter;或者您可以将 Spring Scala 添加到您的类路径中,以启用对 Scala setter 的支持。

使用 @BeanProperty 就像用它注解一个 var 一样简单


class Person(@BeanProperty var firstName: String, @BeanProperty var lastName: String)

这将为该类创建 JavaBean 风格的 setter,因此您可以在 XML 中非常简单地装配它


<bean id="constructor" class="Person" p:firstName="John" p:lastName="Doe"/>

作为使用此注解的替代方案,从 3.2 版本开始,Spring 支持使用 BeanInfoFactory 策略接口的任意 getter 和 setter。Spring Scala 项目包含此接口的实现,该实现支持 Scala getter 和 setter。此实现将由 Spring 自动检测,无需额外配置。

实际上,这意味着将 Spring Scala jar 放在类路径中将启用对 Scala 属性的支持,并且您可以使用上述 XML 配置来装配 Person 类,而无需添加 @BeanProperty 注解。

有关在 Spring XML 中装配 Scala bean 的更多信息,请参阅 Spring Scala 文档维基的相关部分。另请参阅有关在 Spring XML 中装配 Scala 集合的部分。

在 Scala 中装配 Bean

除了在 XML 中定义 bean 之外,Spring Scala 还提供了一种替代方案,它使用 Scala 类而不是 XML 文件来配置您的 Spring bean。这种方法类似于在 Spring Java 中使用 @Configuration,只是它基于函数而不是注解。

要创建函数式 Spring 配置,您只需将 FunctionalConfiguration trait 混入您的配置类中。通过调用 trait 上的 bean 方法并传入创建 bean 的函数来定义 bean。

给定上面显示的 Person 类,我们可以如下在函数式配置中装配它


class PersonConfiguration extends FunctionalConfiguration {
    bean() {
        new Person("John", "Doe")
    }
}

当然,您也可以在特定名称下注册 bean、提供别名或设置作用域


class PersonConfiguration extends FunctionalConfiguration {
    bean("john", aliases = Seq("doe"), scope = BeanDefinition.SCOPE_PROTOTYPE) {
        new Person("John", "Doe")
    }
}

然后,您可以使用此配置类来创建 Spring 应用程序上下文


object PersonConfigurationDriver extends App {
    val applicationContext = new FunctionalConfigApplicationContext(classOf[PersonConfiguration])
    val john = applicationContext.getBean(classOf[Person])
    println(john.firstName)
}

有关函数式 Bean 配置的更多信息,包括强类型 bean 引用、如何导入 XML 文件和 @Configuration 类以及如何将 bean 定义包装在配置文件中的部分,请参阅 Spring Scala 文档维基的相关部分

在 Scala 中使用 Spring 模板

Spring 的模板是有用的工具类,它们有助于各种数据访问或资源处理。Spring Scala 包含适配器,它们将 (Java) 模板调整为更适合 Scala。通常,这些 Scala 模板适配器在 Scala 语言中的使用方面比 Java 版本有三个改进

  • 使用函数而不是回调接口
  • 在 Java 版本可能返回 null 的地方使用 Option
  • 使用类清单而不是类参数

通过这三个改进,您可以例如如下使用 JmsTemplate


val connectionFactory : ConnectionFactory = ...
val template = new JmsTemplate(connectionFactory)

template.send("queue") {
    session: Session => session.createTextMessage("Hello World")
}

template.receive("queue") match {
    case Some(textMessage: TextMessage) => println(textMessage.getText)
    case _ => println("No text message received")
}

通常,模板适配器的 Scala 版本与其 Java 对应版本位于相同的包中,只是中间有一个 scala 包。因此,JmsTemplate 的 Scala 版本位于 org.springframework.scala.jms.core 中,例如。截至撰写本文时,存在以下 Scala 友好的模板

  • SimpleJdbcTemplate
  • JmsTemplate
  • RestTemplate
  • TransactionTemplate

有关在 Scala 中使用 Spring 模板的更多信息,请参阅 Spring Scala 文档维基的相关部分

可用性

Spring Scala 的第一个里程碑版本可在我们的里程碑存储库下载,http://repo.springsource.org/libs-milestone。对于 Maven 用户

<repositories>
    <repository>
        <id>milestone.repo.springsource.org</id>
        <name>repo.springsource.org-milestone</name>
        <url>https://repo.springsource.org/libs-milestone</url>
    </repository>
</repositories>
<dependency>
    <groupId>org.springframework.scala</groupId>
    <artifactId>spring-scala</artifactId>
    <version>1.0.0.M2</version>
</dependency>

项目本身可在 GitHub 获取。如果您想贡献,可以通过为功能请求提交 JIRA,或在 GitHub 上留下拉取请求。

请注意,截至 2013-04-02,已发布新的里程碑版本。请阅读论坛公告

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有