日曜日, 4月 07, 2013

Spring 基本のキホン2 - コレクションをインジェクト

Spring CollectionsのDI

Springの基本第二弾としてCollectionsのインジェクトを選んでみた.とはいえ,Collectionsのインジェクションの機能は正直言って個人的に微妙である.何故微妙なのか?理由は2つある.まず1つめには,Collectionsをコンテクストファイルに記述しればコンテクストファイルが冗長になって可読性が低くなる.2つ目に一般的にプロパティファイルのプロパティの数は決して少なくないしプロダクトがサポートしなければいけない環境又はインスタンスの数が多い場合はこういったプロパティファイルはビルド時に自動生成する.勿論,コンテクストファイルを自動生成する手もあるにはあるが,今のところは私のチームではやっていない.

とはいえ,非常に便利な機能には違いがないので,是非私たちのツールセットの一つに加えておきたい.

サンプル

ここでは一つのJavaクラス,1つのコンテクストファイルそして実行確認用に1つのテストクラスを用意している.
そんな特別なことはなく,単にSet,Map,List,Propertyのフィールドとセッターを注入対象クラスに定義し,コンテクストファイルにはそれぞれに対応するpropertyタグを定義する.Listならlistタグ,MapならMapタグ,Setならセットタグ,Propertiesならpropsタグを定義.ListならびにSetのエレメント定義にはvalueタグ,Mapならentryタグ,Propertiesならばpropタグを使うこと.

CollectionsHolder.java


package org.tanuneko.spring;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class CollectionsHolder {

private List<String> strList;
private Set<String> strSet;
private Map<Integer,String> strMap;
private Properties props;

public List<String> getStrList() { return strList; }
public Set<String> getStrSet() { return strSet; }
public Map<Integer,String> getStrMap() { return strMap; }
public Properties getProps() { return props; }

public void setStrList(List<String> strList ) {
this.strList = strList;
}

public void setStrSet(Set<String> strSet) {
this.strSet = strSet;
}

public void setStrMap(Map<Integer,String> strMap) {
this.strMap = strMap;
}

public void setProps(Properties props ) {
this.props = props;
}

}

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">
   
    <bean id="colHolder" class="org.tanuneko.spring.CollectionsHolder">
        <!-- injecting list -->
    <property name="strList">
    <list>
    <value>Cat</value>
    <value>Dog</value>
    <value>Dog</value>
    </list>
    </property>
    <!-- injecting set -->
    <property name="strSet">
    <set>
    <value>Okachimachi</value>
    <value>Brooklyn</value>
    <value>Brooklyn</value>
    </set>
    </property>
    <!-- injecting map -->
    <property name="strMap">
    <map>
    <entry key="1" value="Vanderbilt St"/>
    <entry key="2" value="Willoghby St"/>
    </map>
    </property>
    <!-- injecting map -->
    <property name="props">
    <props>
    <prop key="prop.shape.name">Triangle</prop>
    <prop key="prop.shape.height">12.5</prop>
    <prop key="prop.shape.base">7</prop>
    </props>
    </property>
    </bean>

</beans>

SpringSampleTest.java

package org.tanuneko.spring;

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 testListHolder() {
CollectionsHolder holder = (CollectionsHolder)ctx.getBean( "colHolder" );
// list.
assertThat( holder.getStrList().get( 0 ), is( "Cat" ) );
assertThat( holder.getStrList().get( 1 ), is( "Dog" ) );
assertThat( holder.getStrList().get( 2 ), is( "Dog" ) );
// Set. In different with list set won't allow to have any dupe entries
for( String str: holder.getStrSet() ) {
assertThat( str, anyOf( is("Okachimachi"), is("Brooklyn" ) ) );
}
assertThat( holder.getStrSet().size(), is( 2 ) );
// Map. Similarly to set no dupe entries are allowed. O(1) reachable unless there are conflicts
assertThat( holder.getStrMap().get( 1 ), is( "Vanderbilt St" ) );
assertThat( holder.getStrMap().get( 2 ), is( "Willoghby St" ) );
// Properties. O(1) reachable for arbitrary keys
assertThat( (String)holder.getProps().get( "prop.shape.name"), is( "Triangle" ) );
assertThat( ( Double.parseDouble( (String)holder.getProps().get( "prop.shape.height" ) ) *
     Double.parseDouble( (String)holder.getProps().get( "prop.shape.base" ) ) ) / 2,
     is( 43.75 ) );
}
}


0 件のコメント: