Springについて DIコンテナ

特徴

Springを適用したプロジェクトはDI×AOPコンテナを持ち、構造が疎結合を意識したものになります。これにより変更、テストが容易になり、コンポーネントの再利用性も高まります。またAOPを利用すればトランザクションを分離させることができ、可読性や保守性の向上が得られます。

DIコンテナ

通常であれば、mainメソッドを持つクラスA、業務ロジッククラスB、DaoクラスCとあった場合、AがBを、BがCをnewしてインスタンスを生成して利用すると思います。
DIを利用した場合、Aが使うBのインスタンス、Bが使うCのインスタンスを、DIコンテナが生成してくれるようになります。

アノテーションを使ったDI

どのようにDIを利用するかを解説します。

Eclipseメニューの新規からSpringプロジェクトを選択し(なければその他から選択)、テンプレートはSimpleSpringMavenを選択し作成してください。
Src/main/javaにsample01パッケージを作成し以下のものを作成してください。
Appクラス/Productクラス/SampleLogicインタフェース/SampleLogicImplクラス/
SampleDaoインタフェース/ProductDaoImplクラス/applicationContext.xml

package sample01;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

	public static void main (String[] args){
		App app = new App();
		app.execute();
	}

	private void execute() {
		@SuppressWarnings("resource")
		ApplicationContext context = new ClassPathXmlApplicationContext("sample01/applicationContext.xml");
		SampleLogic sampleLogic = context.getBean(SampleLogic.class);
		Product product = sampleLogic.findProduct();
		System.out.println(product);
	}
}
package sample01;

public interface SampleLogic {
	Product findProduct();

}
package sample01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SampleLogicImpl implements SampleLogic{
	@Autowired
	private SampleDao sampleDao;

	public Product findProduct(){
		return sampleDao.findProduct("ホチキス");
	}

}
package sample01;

public interface SampleDao {
	Product findProduct(String name);

}
package sample01;

import org.springframework.stereotype.Component;

@Component
public class SampleDaoImpl implements SampleDao{
	//サンプルのためDaoですがDBは使いません
	public Product findProduct(String name){
		//Daoのような振る舞いをしてるだけ
		return new Product(name, 100);
	}

}
package sample01;

public class Product {
	private String name;
	private int price;

	public Product(String name, int price){
		this.name = name;
		this.price = price;
	}
	public String getName(){
		return name;
	}
	public int getPrice(){
		return price;
	}
	@Override
	public String toString(){
		return "Product [name = " + name +", price = " + price + "]";
	}

}
<?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">

	<!-- @Autowiredを利用する場合の宣言 -->
	<context:annotation-config />
	<!-- @Componentを利用する場合の宣言 base-package属性で指定したパッケージ名以下のコンポーネントを検索する -->
	<context:component-scan base-package="sample01" />

</beans>

この@Autowiredをインスタンス変数の目につけると@Componentが付いているクラスの中から探し出し、そのクラスのインスタンスをインジェクションしてくれます。
@Componentが付与されたクラスが、複数あったとしても型が違えば@Autowiredがついてる変数にインジェクションされることはありません。
この、Componentを探しだす範囲をBean定義ファイル(applicationContext.xml)で決めます。

Bean定義ファイルでDI

ここでは上記ででたBean定義ファイルを利用したDIの利用を解説します。
今回のDIコンテナの実体は、BeanFactoryと呼ばれるインターフェースとクラス群がBean定義ファイルに基づいてインスタンスを生成し、インジェクションされます。

サンプルを提示するので上記のプロジェクトにsample02というパッケージを新規に作成し上記と同じファイルを作成してください

package sample02;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

	public static void main(String[] args){
		App app = new App();
		app.execute();
	}

	private void execute() {
		@SuppressWarnings("resource")
		BeanFactory beanFactory = new ClassPathXmlApplicationContext("sample02/applicationContext.xml");
		SampleLogic sampleLogic = beanFactory.getBean(SampleLogic.class);
		Product product = sampleLogic.findProduct();
		System.out.println(product);

	}

}
package sample02;

public class SampleDaoImpl implements SampleDao{
	//サンプルのためDaoですがDBは使いません
	public Product findProduct(String name){
		//Daoのような振る舞いをしてるだけ
		return new Product(name, 200);
	}

}
package sample02;

public class SampleLogicImpl implements SampleLogic{
	private SampleDao sampleDao;

	public Product findProduct(){
		return sampleDao.findProduct("ボールペン");
	}

	public void setProductDao(SampleDao sampleDao){
		this.sampleDao = sampleDao;
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="SampleLogic" class="sample02.SampleLogicImpl" autowire="byType" />
	<bean id="SampleDao" class="sample02.SampleDaoImpl" />

</beans>

記載されてないクラスについては上記のパッケージと同じコードを使用しています。

今回@Componentと@Autowiredのアノテーションがなくなっています。
同じことを実現するためBean定義ファイルを変更しています。
またSampleLogicImplクラスにはインジェクションのためのSetterメソッドが追記されています。

この記事を読んだ人は以下の記事も読んでいます

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA