先ほど、Spring Bootの小さなサンプル(というか写経)を書きましたが、ついでにDI/ComponentScanも試してみたくなりまして。
書籍のCommandLineRunnerの例を、Scalaで書いてみました。
まずは、pom.xml。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.littlewings</groupId> <artifactId>spring-boot-di-cli</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.1.9.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>${scala.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> </execution> </executions> <configuration> <scalaVersion>${scala.version}</scalaVersion> <args> <arg>-Xlint</arg> <arg>-unchecked</arg> <arg>-deprecation</arg> <arg>-feature</arg> </args> <recompileMode>incremental</recompileMode> </configuration> </plugin> </plugins> </build> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <scala.version>2.11.4</scala.version> </properties> </project>
Calculatorの部分。
src/main/scala/org/littlewings/springboot/app/Calculator.scala
package org.littlewings.springboot.app import org.springframework.stereotype.Component trait Calculator { def calc(a: Int, b: Int): Int } @Component class AddCalculator extends Calculator { override def calc(a: Int, b: Int): Int = a + b }
インターフェース(Scalaではトレイト)と実装を分けるのが面倒だったので、1ファイルにまとめました…。
ArgumentResolverも同様。
src/main/scala/org/littlewings/springboot/app/ArgumentResolver.scala
package org.littlewings.springboot.app import java.io.InputStream import java.util.Scanner import org.springframework.stereotype.Component trait ArgumentResolver { def resolve(stream: InputStream): Argument } @Component class ScannerArgumentResolver extends ArgumentResolver { override def resolve(stream: InputStream): Argument = { val scanner = new Scanner(stream) val a = scanner.nextInt() val b = scanner.nextInt() Argument(a, b) } }
Argumentは、今回はCase Classにしました。
src/main/scala/org/littlewings/springboot/app/Argument.scala
package org.littlewings.springboot.app case class Argument(a: Int, b: Int)
プログラムのエントリポイント。
src/main/scala/org/littlewings/springboot/App.scala
package org.littlewings.springboot import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.{ CommandLineRunner, SpringApplication } import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.context.annotation.ComponentScan import org.littlewings.springboot.app.{ ArgumentResolver, Calculator } object App { def main(args: Array[String]): Unit = SpringApplication.run(classOf[App], args: _*) } @EnableAutoConfiguration @ComponentScan class App @Autowired()(private val argumentResolver: ArgumentResolver, private val calculator: Calculator) extends CommandLineRunner { @throws(classOf[Exception]) override def run(strings: String*): Unit = { print("Enter 2 numbers like 'a b' : ") val argument = argumentResolver.resolve(System.in) val result = calculator.calc(argument.a, argument.b) println(s"result = $result") } }
2014/11/26 追記)
最初は以下のようにフィールドインジェクションだったのですが、
@Autowired private val argumentResolver: ArgumentResolver = null
@maikingさんに突っ込まれまして
@kazuhira_r scala + valならコンストラクタインジェクションが良いいような。。
確かに…というわけで、修正しました。
実行。
$ mvn spring-boot:run
動作確認。
Enter 2 numbers like 'a b' : 100 200 result = 300
OKです!
プログラム自体の内容は、説明しません。「はじめてのSpring Boot」を買いましょう。