Spring
Springを上手く使いこなすことができれば,DI/IOCをエレガントにこなすことが出来る.オブジェクトの初期化やインスタンス生成でぐちゃぐちゃしたコードを書きたくない,テスト用DIをスマートに行いたい,JDBCやHibernate等をもう少し綺麗に書きたい,と思っておれば是非Springを試してみてほしい.
Spring サンプル
Springの基礎を丁寧に解説しているページはネットにゴマンとあるので,ここでは基本のキホンのサンプルと簡略な説明にとどめておく.
このサンプルでは4つのクラス,1つのインターフェース,1つのコンテクストxmlを使用する.
まずは土台となるBeanIFインタフェースとSpringSampleクラス.
DIに適用するクラスはテスト用・実働用に別のクラスを注入できるようにするため,インターフェース又は抽象クラスであるべき.
BeanIF.java
public interface BeanIF {
int getInstanciationCounter();
String getMessage();
}
SpringSample.java
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("sample")
@Scope("prototype")
public class SpringSample implements BeanIF {
private static int instanciationCounter = 0;
@Autowired
private Injectee inject;
@Resource
private Injectee2 inject2;
public SpringSample() {
instanciationCounter++;
}
public int getInstanciationCounter() {
return instanciationCounter;
}
public void getMessage() {
return inject.showMessage() + ":" + inject2.showMessage();
}
}
上記クラスでは4つのアノテーションを使っている.
Component .. Spring Bean Management Frameworkで管理されるPojoに汎用的に使われる.
Controller,Repository,ServiceもSpring Mojoとしてクラスをマークするが用途は違う.
Scope .. Singletonは最初のPojo登録の時にのみクラスは初期化される.prototypeはgetBean()されるたびに別のインスタンスが帰ってくる.
Autowired .. 型が合致又は継承又はインターフェース実現クラスであれば自動的に注入.requiredパラメータを使えばautowiringが失敗した場合の挙動も制御できる.Spring由来.
Resource .. Autowiredの条件+PojoのIdが合致する場合に注入.JSR250由来.Autowired + QualifierはResourceとほぼ同様の振る舞いになる.
次にInjecteeとinjectee2 - それぞれautowired又はResourceでDIされる - を見てみる.
@Component("inject")
public class Injectee {
public void showMessage() {
return "Injected.";
}
}
@Component("inject2")
public class Injectee2 {
public String showMessage() {
return "injectee2";
}
}
Componentアノテーションによりこれら2つのクラスもまたSpringにより管理化に置かれる.
ではどのようにこのアノテーションドリブンによるPojoの検索・登録がおこなわれるのか.
キーはcontext.xmlにある.
<?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="myapp.package" />
</beans>
context:annotation-configでautowired等のアノテーションを有効にし,context:component-scanにて指定されたパッケージ以下をSpringがスキャンし,Componentアノテーション等でマークアップされたクラスを登録し,autowiring等も行う.contextネームスペースを使う際,xmlns.contextをbeansタグに追加することを忘れないこと.
これでPojoの用意及び依存性注入も出来たはずなので,実際以下のテストクラスを使って試してみる.
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.hamcrest.CoreMatchers.*;
/**
* Unit test for simple App.
*/
public class SpringSampleTest {
static ApplicationContext ctx = null;
@BeforeClass
public static void prep() {
ctx = new ClassPathXmlApplicationContext( "spring/context.xml" );
}
@Test
public void testBase() {
SpringSample sample = (SpringSample)ctx.getBean( "sample" );
sample = (SpringSample)ctx.getBean( "sample" );
assertThat( sample.getMessage(), is( "injectee:injectee2" ) );
assertThat( sample.getInstanciationCounter(), is( 2 ) );
}
}
テストが成功すれば,依存性注入も成功し,prototypeの挙動も確認できていることとなる.
Springは結構丁寧なロギングをしているので,もしその情報を見たければlog4j又はslf4j api + slf4j-log4j12を使う必要がある.
0 件のコメント:
コメントを投稿