Spring Framework 入門記 Contextその4 リソース
今回は「3.10.3. Using resources within Spring」です.早く3章終わらせたいよっ! AOP(5章)に行きたいよっ!
ここでいうリソースは,URLで示されるものやファイルなどのことで,おおざっぱに言えばjava.io.InputStream
で内容を読み込むことができるようなものです(たぶん).java.lang.ClassLoader#getResource(String)
でいうところのリソースと同じようなものですね.
リソースを手に入れるには,ApplicationContext#getResource(String)
を使います.このメソッドの引数をlocation
と呼びます.ソース上でそうなっているので.それでですね,そのlocation
の解釈は,ApplicationContext
の実装によって異なるみたいです.ちなみにFileSystemXmlApplicationContext
*1の場合は次のようになっているようです.
location
が"classpath:"
で始まっている場合,その後続の文字列は(先頭が'/'
で始まっている場合はそれを取り除いて)クラスパス上のリソースとして扱われます.location
をURLとして解釈できれば(MalformedURLException
がスローされなければ),そのURで示されるリソースとして扱われます.- それ以外はファイルシステム上のリソースとして扱われます.ただし,
location
の先頭が'/'
で始まっている場合は取り除かれます.
という具合です.最後のやつは,WEBアプリケーションで都合がいいようにってことらしいです.
ApplicationContext#getResource(String)
の戻り値は,Resource
というインタフェースです.これは,次のメソッドを持っています.
getInputStream()
getURL()
getFile()
exists()
isOpen()
getDescription()
どんなリソースでも,全てのメソッドが有効というわけではありません."file:"
でないURLで示されるリソースでは,getFile()
は例外を吹っ飛ばしてくれます.
こんな感じでリソースを手に入れて,InputStream
を通して内容を読み込むことができるのですが,これはやっぱりApplicationContext
の機能なんですよね.またApplicationContext
に依存するのか? なんて思いますよね.その程度のことでApplicationContextAware
をimplements
しなきゃいけないのか? なんて思いますよね.
ご安心ください.そんなあなた(誰?)のために,ResourceEditor
をご用意させていただきました*2.え? それは何だって? それはですね,PropertyEditor
の実装なんですねー.覚えてますか,PropertyEditor
.そう,文字列をプロパティの型に変換する,あのプロパティエディタです.BigDecimal
なプロパティに値を設定するために使った,あのプロパティエディタです(遠くを見る目).こいつを使うと,Resource
なプロパティにsetterで値を設定できちゃうんですねー.もちろん,コンストラクタにも使えるでしょうとも.
あれ? でも結局,Resource
には依存しちゃうのね.Springとは無関係なBeanとして使えるわけではないのですね.それくらいだったら,素直にjava.io.File
やjava.net.URL
のプロパティを持つようにした方がいい感じがするなぁ.あ,でもそれだとクラスパスから取ってくることができないのか.うー,なんか今ひとつ.しょうがない,java.io.InputStream
のプロパティで手を打つことにしようか.
なお,ResourceEditor
はApplicationContext
を使用していません.(^^;
実は,getResource(String)
は,ResourceLoader
のメソッドで,ApplicationContext
はそれをextends
しているんですね.それでResourceEditor
が使用するResourceLoader
の実装は,location
引数の解釈がFileSystemXmlApplicationContext
とは微妙に異なり,ファイルシステムを見てくれません.なんだかなー,今はApplicationContext
のお勉強中なのにぃ.
いずれにせよ,あんまり嬉しい代物じゃない気がしてしょうがないんですが,逃げちゃダメですか? そうですかダメですか.無念だ.
やむを得ません,お試ししましょう.
今はApplicationContext
の学習中なので,とりあえずは素直にApplicationContextAware
なクラスを作ってみます.
package study; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class ResourceChecker implements ApplicationContextAware { private ApplicationContext context; private String location; public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public boolean isExists() { return context.getResource(location).exists(); } }
こいつは,指定されたりソースが存在するかどうかを示すboolean
のread onlyなプロパティを持っています.面倒なので内容を読み込むようなことはしていません.心より恥じる.
次にBean定義のXMLファイル.いつも通り<bean>
要素のみの抜粋.
<bean id="file" class="study.ResourceChecker"> <property name="location"><value>beans.xml</value></property> </bean> <bean id="url" class="study.ResourceChecker"> <property name="location"><value>http://java.sun.com/ </bean> <bean id="classpath" class="study.ResourceChecker"> <property name="location"><value>classpath:study/Main.class</value></property> </bean> <bean id="notfound" class="study.ResourceChecker"> <property name="location"><value>notfound</value></property> </bean>
location
を何パターンかご用意させていただきました.
これを入門記の「Contextその1」で作成した実行用のクラスで実行します.
file : study.ResourceChecker@13e58d4 class=class study.ResourceChecker exists=true location=beans.xml url : study.ResourceChecker@39e5b5 class=class study.ResourceChecker exists=true location=http://java.sun.com/ classpath : study.ResourceChecker@32efa7 class=class study.ResourceChecker exists=false location=classpath:study/Main.class notfound : study.ResourceChecker@13c7378 class=class study.ResourceChecker exists=false location=notfound
こんなもんでいっか.あまり楽しいものではなかったですね.ま,必要になったら思い出すということで.
さぁ,3章も残りはあと少し! 頑張るぞぉ.