---
title: スッキリ！SpringでJSR-330を使うための最小サンプル
tags: []
categories: ["Programming", "Java", "org", "springframework"]
date: 2013-08-12T14:41:24Z
updated: 2013-08-12T14:41:24Z
---

[ℹ️ **Spring 5.3版で書き直しました**](/entries/662)

SpringはJSR-330 (DI)を実装している。
JSR-330の実装でスタンドアローンで使うならGuiceだよねーという声が聞こえたので、Springでも結構さくっと使えるよっていうサンプル。
XMLはいまや不要ですよ。

全部でこれだけ

<a href='/api/v1/files/00109/spring-jsr330.png'><img src='/api/v1/files/00109/spring-jsr330.png' /></a>


### 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のサンプルも作ろう
