IK.AM

@making's tech note


スッキリ!SpringでJSR-330を使うための最小サンプル

🗃 {Programming/Java/org/springframework}
🗓 Updated at 2013-08-12T14:41:24Z  🗓 Created at 2013-08-12T14:41:24Z   🌎 English Page

ℹ️ Spring 5.3版で書き直しました

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


✒️️ Edit  ⏰ History  🗑 Delete