Spring2(DIxAOP)
はじめに
Springは、Javaでアプリケーションを作成する上で欠かすことのできないフレームワークです。 Springの中心的な機能であるDIxAOPのうちDIについてご紹介します。。
以下の内容をご紹介します。
(1)DI
DIは、「依存性の注入」と呼ばれ、インターフェースを利用した部品化を実現するものです。
依存性のある外部プログラムを取り入れることで、オブジェクト間の依存を取り除くということです。
DIを実現するには、次の3種類があります。
《DIの実現方法》
- アノテーションを用いたDI
- XML形式のBean定義ファイルを用いたDI
- Javaプログラムを用いたDI
1-1 アノテーションを用いたDI
DIコンテナに登録したいクラス宣言の前に@Componentアノテーションを追加します。また、DIコンテナに注入したいインスタンス(変数、メソッド、コンストラクタ)宣言の前に@Autowiredを記述します。ただし、DIを有効にするには、XML形式のBean定義ファイルかJavaプログラムと併用する必要があります。
1-2 XML形式のBean定義ファイルを用いたDI
「1-1 アノテーションを用いたDI」は、小規模開発で非常に便利です。しかし、大規模開発ではXML形式のBean定義ファイルを利用してDI管理を行います。XML形式のBean定義ファイル名は、「applicationContext.xml」とするのが慣習です。XML形式でBean定義を行うことで、アノテーションをクラスやインスタンスに記述しなくてもDIを実現できるようになります。
また、「1-1 アノテーションを用いたDI」と「Bean定義ファイルを用いたDI」を併用することもよくあります。
1-3 Javaプログラムを用いたDI
DIを実現するためのJavaプログラムをJavaConfigといいます。 「1-2 XML形式のBean定義ファイル」と比べて、JavaConfigはJavaプログラムなので、タイプセーフ(クラス名などの誤りをコンパイルで検知できる)です。JavaConfigは、1人で開発を行う場合に便利ですが、大規模開発でも使えます。XML形式によるBean定義ファイルかJavaConfigかは、コードの可読性や保守性を考えて選択することが重要です。
「1-1 アノテーションを用いたDI」のサンプルコードをご紹介します。 各クラスの階層関係は、次のようになります。
【各クラスの階層関係】
<!-- applicationContext.xml
アノテーションを有効にするためのxml形式のBean定義ファイル-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:component-scan base-package="sample.di.business" />
<context:component-scan base-package="sample.di.dataaccess" />
</beans>
//プレゼンテーション層パッケージ
package sample;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import sample.di.business.domain.DataRegister;
import sample.di.business.service.DataCall;
//コントローラの代わとしてmain()メソッドを実行する
public class SampleRun {
public static void main(String[] args) {
SampleRun sampleRun = new SampleRun();
sampleRun.execute();
}
@SuppressWarnings("resource") //DIを実現するアノテーションではない
public void execute() {
String path = "/sample/config/applicationContext.xml";
BeanFactory ctx = new ClassPathXmlApplicationContext(path);
DataCall dataCall = ctx.getBean(DataCall.class);
dataCall.addProduct(new DataRegister("ペン", 100));
DataRegister dataRegister_Pen = dataCall.findByProductName("ペン");
System.out.println(dataRegister_Pen);
}
}
//ビジネスロジック層(サービス)パッケージ
package sample.di.business.service;
import sample.di.business.domain.DataRegister;
//インタフェース
//プレゼンテーション層からサービスを呼び出す
public interface DataCall {
void addProduct(DataRegister dataRegister);
DataRegister findByProductName(String name);
}
//ビジネスロジック層(サービス)パッケージ
package sample.di.business.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sample.di.business.domain.DataRegister;
//DataCallインタフェースの実装クラス
@Component //DIコンテナに登録
public class DataCallImpl implements DataCall {
@Autowired //DIコンテナに注入したいインスタンス
private DataMap dataMap;
@Override
public void addProduct(DataRegister dataRegister) { dataMap.addProduct(dataRegister); }
@Override
public DataRegister findByProductName(String name) { return dataMap.findByProductName(name); }
}
//ビジネスロジック層(サービス)パッケージ
package sample.di.business.service;
import sample.di.business.domain.DataRegister;
//インタフェース
//データアクセス層とやり取りする
public interface DataMap {
void addProduct(DataRegister dataRegister);
DataRegister findByProductName(String name);
}
//ビジネスロジック層(ドメイン)パッケージ
package sample.di.business.domain;
//サービスから呼び出されたらサービスにデータを返す
public class DataRegister {
private String name;
private int price;
public DataRegister(String name , int price) {
this.name = name;
this.price = price;
}
public String getName() { return name; }
public int getPrice() { return price; }
@Override //DIを実現するアノテーションではない
public String toString(){ return "name=" + name +", price=" + price; }
}
//データアクセス層パッケージ
package sample.di.dataaccess;
import java.util.HashMap;
import java.util.Map;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import sample.di.business.domain.DataRegister;
import sample.di.business.service.DataMap;
//データベースの代わりとしてMapを利用
@Component //DIコンテナに登録
public class DataMapImpl implements DataMap {
private Map<String, DataRegister> storage = new HashMap<String , DataRegister>();
@Override
public DataRegister findByProductName(String name) { return storage.get(name); }
public void addProduct(DataRegister dataRegister) { storage.put(dataRegister.getName(), dataRegister); }
}
name=ペン, price=100
まとめ
「DI概要」についてご紹介しました。
お役に立てると幸いです。
↑
関連記事一覧