自作DI①
SpringやCDIで提供されるDIの仕組だが、いろいろ原理主義的で扱いにくいところがあるため、やりやすいようにDIを自作してみる。
最終形として
・アノテーションベース
・XMLの設定ファイルでインジェクションするクラスを指定
を想定して作っていこうと思っている。
DIの仕組を考える前に、今日は設定ファイルに使おうと思っているXMLのJavaからの扱い方を復習してみたい。
有名どころのDOMのライブラリにて、かつてハマったところも鑑みて使い方をみていく。
test.xml
<?xml version="1.0" encoding="UTF-8"?> <factor1> <factor2> <factor3>value3</factor3> <factor4>value4</factor4> </factor2> </factor1>
このxmlファイルをパースしてDocumentクラスのインスタンスに展開。
package xmltest; import java.io.File; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; public class XmlTest { public static void main(String args[]){ try{ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder(). parse(new File("C:\\test.xml")); }catch(Exception e){ e.printStackTrace(); } } }
XMLドキュメントの根幹であるDocumentのインスタンスは、内部でDOMツリーの構造を成している。
ドキュメント内の各要素をNodeとして取り出すことが出来、子要素は各NodeからNodeとして取り出すことが出来る。
複数Nodeを取り出す際にはNodeList型というのもある。ちなみにIterableではない。
Nodeを辿って目的の子ノードを探すことも出来るが、getElementsByTagNameで特定のtag名を持つNodeを再帰的に取ってくることも出来る。
ちょっとハマるのが、タグだけでなくタグ外のテキストもNodeとして扱われることだ。test.xmlの例で言えば、factor2からgetChildNodes()でNodeListを取得した場合、中のNodeは
・factor2の後ろの改行コード+インデント
・factor3
・factor3の後ろの改行コード+インデント
・factor4
・factor4の後ろの改行コード+インデント
の5つになる。なので無考慮にgetFirstChild()で最初のタグを処理しようとすると失敗する。かと言ってtext上タグを完全に隣接させれば最初のNodeがタグになるため、2番目のNodeを最初のタグとすることも出来ない。
NodeNameを確認して処理するなど、きちんとチェックを行うことが必要になる。
package xmltest; import java.io.File; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class XmlTest { public static void main(String args[]){ try{ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder(). parse(new File("C:\\test.xml")); Node nodeTest1 = doc.getFirstChild(); System.out.println("--test1---"); System.out.print("name:" + nodeTest1.getNodeName()); System.out.print(",type:" + nodeTest1.getNodeType()); System.out.println(",value:" + nodeTest1.getNodeValue()); System.out.println("----------"); Node nodeTest2 = doc.getFirstChild().getChildNodes().item(0); System.out.println("--test2---"); System.out.print("name:" + nodeTest2.getNodeName()); System.out.print(",type:" + nodeTest2.getNodeType()); System.out.println(",value:" + nodeTest2.getNodeValue()); System.out.println("----------"); NodeList parentNl = doc.getElementsByTagName("factor2"); NodeList childNl = parentNl.item(0).getChildNodes(); System.out.println("--test3---"); for(int i = 0;i < childNl.getLength();i++){ Node nodeTest3 = childNl.item(i); System.out.print("name:" + nodeTest3.getNodeName()); System.out.print(",type:" + nodeTest3.getNodeType()); System.out.println(",value:" + nodeTest3.getNodeValue()); } System.out.println("----------"); }catch(Exception e){ e.printStackTrace(); } } }
実行結果
--test1--- name:factor1,type:1,value:null ---------- --test2--- name:#text,type:3,value: ---------- --test3--- name:#text,type:3,value: name:factor3,type:1,value:null name:#text,type:3,value: name:factor4,type:1,value:null name:#text,type:3,value: ----------