SpringはJSR-330 (DI)を実装している。 JSR-330の実装でスタンドアローンで使うならGuiceだよねーという声が聞こえたので、Springでも結構さくっと使えるよっていうサンプル。 XMLはいまや不要ですよ。
全部でこれだけ
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>minimam-spring-jsr330</groupId>
<artifactId>minimam-spring-jsr330</artifactId>
<version>1.0.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
</project>
DIを使うだけならspring-contextだけで十分(AOPもついてきますが)
コンポーネント作成
package sample;
import javax.inject.Named;
@Named
public class GreetingService {
public String hello(String message) {
return "Hello " + message + "!";
}
}
@Named
をつけておけば後で設定するコンポーネントスキャンにより、DIコンテナに管理されます。
JSR-330準拠だとデフォルトscopeがprototype(毎回生成)になります。
JSRにこだわらなければ@Service
とか@Component
とか責務のわかるアノテーション付ける方が好き。
Injectionする
コンポーネントを使う側
package sample;
import javax.inject.Inject;
public class MyApp {
@Inject
protected GreetingService greetingService;
public void run(String message) {
System.out.println(greetingService.hello(message));
}
}
@Inject
でインジェクションします。
JavaConfig
SpringおなじみのBean定義XMLファイルの代わりにJavaでBean定義できます。
package sample;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Jsr330ScopeMetadataResolver;
@Configuration
@ComponentScan(basePackages = "sample", scopeResolver = Jsr330ScopeMetadataResolver.class)
public class AppConfig {
@Bean
public MyApp myApp() {
return new MyApp();
}
}
@Configuration
つけるとBean定義ファイル相当になります。@Bean
をつけたメソッドが返すオブジェクトがDIコンテナに管理されます。<bean class="sample.MyApp" />
と同義。
また@ComponentScan
で指定したパッケージ以下のクラスで@Named
がついているものは自動でDIコンテナに登録されます。<contect:component-scan base-packages="sample">
相当。
Jsr330ScopeMetadataResolverを指定するとJSR-330準拠になり、デフォルトscopeがprototypeになります。指定しなければSpringの慣習に合わせてデフォルトscopeがsingletonになります。
エントリポイント
package sample;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
public class Main {
public static void main(String[] args) {
try (GenericApplicationContext applicationContext =
new AnnotationConfigApplicationContext(AppConfig.class)) {
MyApp app = applicationContext.getBean(MyApp.class);
app.run("World");
}
}
}
AnnotationConfigApplicationContext
にJavaConfigファイルを渡してDIコンテナ作成。
getBeanでDIコンテナに管理されたBeanを取得できます。タイプセーフです。
簡単だったでしょ?Springはいまはかなりシンプルに使えます。
Todo
GuiceのサンプルとWeldのサンプルも作ろう