Spring/Struts/Hibernateのベストプラクティスについて書きたいなと思います。といっても、Strutsは使っているのですがHibernateとSpringは今回初めてなので、業務ロジックを実装する為の準備編について書きます。間違っているかもよくわからないまま始めているので、突っ込みとか、もっといい方法あるよとか、色々教えていただけると幸いです。
まず、Spring/Struts/Hibernateを組み合わせると確実に設定ファイル地獄になるんですね。大体こんな感じになります。赤字で書かれているものが編集する対象です。
Struts
- struts-config.xml
- validation.xml
- validation-rules.xml
- tiles-def.xml
- messages.properties
- struts-html.tld
- struts-bean.tld
- struts-logic.tld
- struts-nested.tld
- struts-tiles.tld
Hibernate
- hibernate.cfg.xml
- [テーブル名(テーブル数分)].hbm.xml
Spring
SpringのapplicationContext.xmlはこの1ファイルだけで行くのは非現実的なので、実際にはカテゴリや機能単位で分割し、分割されたファイルをapplicationContext.xmlからインポートする方式となります。今回私は、
- applicationContext-aop.xml(汎用的なアスペクトの定義)
- applicationContext-dao.xml(データアクセスオブジェクトの定義)
- applicationContext-datasource.xml(データソースの定義)
- applicationContext-action.xml(アクションの定義)
- applicationContext-page.xml(ビューで使用するBeanの定義)
- applicationContext-service.xml(サービスの定義)
- applicationContext-tx.xml(トランザクションマネージャ及び宣言的トランザクションの定義)
に分割しました。
これだけでもかなりな設定ファイル数ですが、常時みんなで追加・修正することを考えると相当苦労しそうな気配です。そこで、業務系のクラスに関しては、極力設定を書かなくても済む方法をとることにしました。
まずはHibernateですが、注釈によってマッピングの省略が可能になります。また、EJB3と基本的に同じ注釈が利用可能なので、EJB3を使うときにもそのまま流用が可能になります。それでもマッピングオブジェクトを追加するときにhibernate.cfg.xmlを修正するのは大変です。そこで、
- Spring/Hibernate連携用のLocalSessionFactoryBeanを継承
- postProcessConfigurationをオーバーライド
- マッピングクラスを検索
- 検索結果からHibernateの設定ファイルと同等なorg.w3c.Documentのインスタンスを生成
- ConfigurationにXMLを渡す
という感じで動的にマッピングクラスの追加が可能になりました。
次にStrutsですが、Strutsのプラグインで自動登録するようにしました。フローはこんな感じです。
- Spring側で管理されているアクションのインスタンスを検索
- 取得したアクションクラスから設定オブジェクト(FormBeanConfigやActionMapping等)を生成
- ModuleConfigに追加
- 同時にバリデータの定義もアクションフォームから取得
アクションやアクションフォームの設定の情報は独自の注釈で対応しました。
最後にSpringですが、これも工夫する事で自動登録ということが可能になります。
- BeanFactoryPostProcessorを実装したクラスをBeanとして登録
- BeanFactoryに登録されたときに呼び出される
- その呼び出されたところで設定可能なBeanFactoryのインスタンスを取得
- クラスの検索を行ってBeanFactoryに登録する
業務アプリを実装していく中で必要なクラスの類は、これで殆ど登録できるようになりました。
何度も出てきているクラスの検索は、パッケージ名を元に検索するロジックを自前で作っていますが、これが正直一番大変です。クラスパス上のリソースの類は、パスを元にあるかないかを判断する事は出来ますが、ディレクトリを元に子を列挙する事は出来ません。そこでリソースのパスから実体のパスを示すURLオブジェクトを取得して、そのURLがファイルなのかJARファイルなのかを判断して個々のAPIで列挙しています。
長くなったのでこの辺で。次は色々覚えた事を書いていこうかなと思います。