Spring Scala 简介

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

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

为何选择 Spring Scala?

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

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

Spring Scala 概览

Spring Scala 正在进行中。在这篇文章的其余部分,我将重点介绍目前已经实现的功能。然而,我们预计在接下来的几个月会添加许多额外功能,希望是通过您提供的反馈来实现。因此,如果您对某个功能有想法,认为它能让在 Scala 中使用 Spring 更愉快,请通过提交 JIRA 问题 或留言来告诉我们。

在 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 文档 Wiki 的相关章节。另请参阅有关在 Spring XML 中装配 Scala 集合的章节。

在 Scala 中装配 Bean

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

要创建一个函数式 Spring 配置,您只需在配置类中混入 FunctionalConfiguration 特质即可。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 类以及如何在 profile 中包装 Bean 定义的章节,请参阅 Spring Scala 文档 Wiki 的相关章节

在 Scala 中使用 Spring 模板

Spring 的模板是实用的工具类,有助于一般的数据访问或资源处理。Spring Scala 包含一些包装器,可将(Java)模板适配得更适合 Scala 使用。总的来说,这些 Scala 模板包装器在使用时相比 Java 版本有三个改进:

  • 使用函数代替回调接口
  • 在 Java 版本可能返回 null 的地方使用 Option
  • 使用类 manifest 代替类参数

通过这三个改进,您可以如下使用 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 文档 Wiki 的相关章节

可用性

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 提交 pull request 来进行。

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

订阅 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

先行一步

VMware 提供培训和认证,助您快速发展。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举办的活动

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

查看全部