Springは世界中で使用されているフレームワークで、GoogleAppEngineや、VMForceなどでも使用可能になっていて、使い方が分からないと乗り遅れている感があります。
しかし、「じゃあ、Springって何!?」って調べ始めると、DI(依存性の注入)とか、IoC(制御の反転)とか出てきて、「?」が広がっていきます。
ここでは、難しい説明は他の書籍やホームページに任せて、もっと簡単な説明をしてみたいと思います。
説明は自分の解釈で書きますのでそこは注意をお願いしたいところですが、
導入の解釈としてはこれで十分だと思っています(おそらく・・・)
使っていくうちになんとなくDIとか分かっていくものじゃないでしょうか。(たぶん)
【SpringのDIって何?】
ひと言で言うなら、
「設定情報を外部定義化できる機能」
です。
外部定義というと、Windowsでいうとiniファイル、Javaなら.propertiesファイルなどを思い浮かべますが、
それらは固定値をコンパイルなしに変更できる機能です。
Springがすごいところは、
「使用するクラスも外部定義化でき、変更できる」
ところです。
どういうことかは、この後、みていきます。
【Springの外部定義化】
通常、外部定義をする場合、次のような実装をする必要があります。
①外部定義ファイルから値を取り出す機能の実装
②取り出した値を、使用するクラスもしくはメソッドに渡す機能の実装
この程度ならたいしたこと無いでしょ!って思うかもしれませんが、設定が増えてくると
これだけでもかなりのコード量になり、おそろしく大変になります。
Springでは上記のコードを実装する必要がなくなります。
その具体的な例を見ていきましょう!
まず、Springでは外部定義にXMLを使用します。
以下のような感じです。
例では、データをファイル出力することを考えます。
<設定XMLの記述例>
<bean id="fileWriter" class="com.file.MyFileWriter">
<property name="extractor" ref="csvExtractor"/>
</bean>
<bean id="csvExtractor" class="com.file.MyCsvExtrator">
<property name="delimiter" value=","/>
</bean>
beanは1つのクラスを表し、そのクラスをnewした実体を内部で持っています。
id属性は、その実体に名前をつけたものと思ってもらえば大丈夫です。
上記の場合、2つのクラスが登場していて、以下のようにしたのと同じことになります。
MyFileWriter fileWriter = MyFileWriter();
MyCsvExtrator csvExtractor = new MyCsvExtrator();
//propertyタグでの設定は、setterを表す(文字列を設定)
csvExtractor.setDelimiter(",");
//propertyタグでの設定、setterを表す(クラス自体も設定できる)
fileWriter.setExtractor(csvExtractor);
※CsvExtractorは、与えられた1行分のデータをカンマ区切り文字列に変換するクラスとしています。
なんとなく分かるでしょうか?
newして、setterで値を設定しているだけです。
propertyタグはsetterを表していて、値を設定する場合はvalue属性を使用し、クラス(bean)を設定する場合は
ref属性を使用します。
これで、最初の課題であった①②の、値をファイルから取得すること、値をクラスに設定すること、の
2つを実現できているのが分かるでしょうか?
区切り文字も外部定義化できています。
再掲:
<bean id="csvExtractor" class="com.file.MyCsvExtrator">
<property name="delimiter" value=","/> ←ここを" "に変えれば空白区切りになる!!
</bean>
XMLファイルを変更すれば、コンパイルなしに任意の区切り文字にできます!
もちろん、MyFileWriter、CsvExtractorの実装は必要ですが、それはSpringを使用しなくても同じです。
【動作の変更】
お話は、まだまだ続きます!
上記の例では、値の設定だけでなく、クラスも設定しています。
再掲: fileWriter.setExtractor(csvExtractor);
これを利用すると、動作の変更もできます。
<設定XMLの記述例>
<bean id="fileWriter" class="com.file.MyFileWriter">
<property name="extractor" ref="fixedExtractor"/>
</bean>
<bean id="csvExtractor" class="com.file.MyCsvExtrator">
<property name="delimiter" value=","/>
</bean>
<!-- 追記 -->
<bean id="fixedExtractor" class="com.file.MyFixedExtrator">
</bean>
※MyFixedExtratorは、与えられた1行分のデータを固定長で文字列に変換するクラスとしています
fixedExtractorを追記しました。
そして、fileWriterも書き変えています。
再掲:
<bean id="fileWriter" class="com.file.MyFileWriter">
<property name="extractor" ref="fixedExtractor"/> ←設定するクラスを変更しました
</bean>
これだけで、カンマ区切りファイル出力から、固定長によるファイル出力に変わりました。
通常の設定ファイルでも動作を変えることはできますが、相当コードを記述しなければなりません。
しかしSpringでは設定ファイルのためのコード記述は必要なく、ref属性を変更するだけです!
簡単ですよね!
この例でなんとなく分かったかと思いますが、Springを使うと、
「必要な機能の実装のみに専念できる!」
ということになります。
今まで煩わされた外部定義化の実装に工数をかける必要がなくなります!
【設定したクラス(bean)を実際に使用する】
ちょっとあとまわしになりましたが、上記で設定した内容をプログラム上で使用する方法に軽く触れます。
<使用方法例>
//XMLファイルのロード(他にもロードするクラスはあります。状況に合わせて使用するクラスを決めます)
ApplicationContext ac = new FileSystemXmlApplicationContext("c:/app/context.xml");
//クラスの取得
MyFileWriter fileWriter = (MyFileWriter)ac.getBean("fileWriter");
//ファイル出力
fileWriter.output("c:/app/out.txt");
簡単ですよね!
ファイルをロードして、getBean()で指定のbeanを取得するだけです!
さて、さきほどの内容とあわせると、とってもいいことがあります。
それがここでのポイントです
さきほど、MyFixedExtratorを使用するように変更しました。
この影響はあるでしょうか?
上記のプログラムをみると、関係ありそうなところは、ac.getBean("fileWriter");だけです。
しかも、bean名「fileWriter」は変更しないので影響が一切ありません!!
これがポイントです。
Springを適切に使用すれば、拡張も変更も既存のコードを変更することなく容易にできるようになります。
また、変更が容易なため、テスト用のモックに切り替えることも簡単になり、テストの効率が上がります!
Spring導入部の説明は以上です。
ここでの説明は話を簡単にするため、省略している便利な機能がいくつもあります。
あとはどんどん使って実践あるのみです!
【補足】
Springの設定ファイルは、jarファイルの中に含めることがほとんどです。
その場合、jarの中のファイルを変更することは大変です。
でも大丈夫!
当然、Springはそのような場合でも対応できます。
以下を参照してみてください!
・DIの設定ファイルで外部ファイル(プロパティファイル)を参照するには?
参考:
・DIの設定ファイルで外部ファイル(プロパティファイル)を参照するには?
・プロパティファイルをPropertiesクラスのbeanにするには?
Spring Framework について