議事録 / 第04回


6章 軽量コンテナとIoC

Lightweight Container

  • 軽量コンテナの付加価値
    • Clustering
      • これは軽量コンテナがもつべきサービスだろうか?
      • もっと手前(Sessionなど)でクラスタリングするのがいいのでは?
      • 例えば、CosminexusはEJBのコンテナの中にクラスタリング機能を持っている。優先順位付けをして実行、TP1とつなげられるなどの特徴がある。
  • Customization and extensibility
    • どういうことを言っているか?セキュリティーやトランザクションなどコンテナに用意されている以外の機能を自分で作ることができるということではないか。SpringのPost-processorのような機能のことを言っているのかかもしれない。
  • 軽量コンテナの特徴
    • 侵略的(invasiveness)でない。
    • 侵略的とはEJBのように特定のインタフェースの使用を強要することを指す。軽量コンテナの場合はPOJOを使うので侵略的でない。
  • 軽量コンテナを使う理由
    • Consistencyとはどういうことか? → 例えば、シングルトンの作りや設定が開発者ごとにばらばらであったり行き当たりばったりというのを避けるということ。
  • Singletonのハードコーディング
    • Singletonがあるとtestがしにくくなることが問題。
      • あるtestコードでSingletonに値を設定した場合、別のtestコードに影響してしまう。test間の依存関係をなくそうとういうJUnitの思想と合わない。
      • Singletonにはグローバル変数っぽく使われるものとそうでないものがあり前者が問題。read onlyのSingletonは問題ない。
  • ロッド氏が言うところの真のOOはいつ明かされるのか?
    • p.298にビジネスロジックをどのオブジェクトに置くかについてロッド氏の考えが述べられている。
  • RemotingやXMLによるdecouplingが負荷が高いとはどういうことか?
    • リモートを使うと1000倍遅いという話がある。
    • オブジェクトとXMLのマーシャル/アンマーシャルの負荷が高いということを言っているのでは。
  • DAOパターン
    • DAOパターンがストラテジーパターンの特別なケースと言っているがこれはおかしい。同じインタフェースをもった別のDAOに切り替えられるということを言っているのであれば、それはストラテジーパターンというよりは通常のインタフェースの特徴。

Managing Business Objects

  • 唐突に出てくるベストプラクティスとは何を指しているのか?
    • EJBを使うときには、EJBの中に直接ロジックを書くのではなくてPOJOにDelegateしたほうがいいということ。Session Facadeパターン。

Inversion of Control

  • IoCの種類
    • 丸山先生レクチャーシリーズ in 東京 2004 での細川 努氏のスライドにFigure6-1と同等のものが掲載されている。ただ、AvalonのTypeがDependecy Injectionの下に追加されているが、これはDependency Lookupの下につくものだと思われる。
    • Dependecy lookupは一般的な用語なのか? -> 聞いたことがない。
    • そういえばDependecyのTypeをType1、Type2、Type3と分けるのは最近聞かない。IoC自体もあまり聞かなくなっている。
  • Setter Injection と Constructor Injection
    • プロパティがself-documentedとは? → プロパティの名前自体でそれが何を意味するかわかるということ。コンストラクタではそれがわかりにくい。
    • SpringのConstructor Injectionでindexやtypeを指定しなければいけないのはなぜか? → autowiringが関係していると思われる。たとえば、コンストラクタの引数が3つあり、2つを明示的に指定し残りの1つをautowireしたい場合に、どの値が何番目かを示すためにindexやtypeが必要となる。
    • DI設定するならばSetter Injectionを使ったほうがいい。名前が明示的に書けるので何が設定されているのかがわかりやすい。
    • Design by Contractのクラス不変表明を意識すると、コンストラクタで絶対に必要な引数を設定させるという考え方もある。ただ引数が多くなると困る。
    • Seasar2のConnectionPooling?の設定ではSetter Injection と Constructor Injectionが混在している。必須のものはコンストラクタで設定し任意のものはセッターで設定している。
  • Dependecy Injectionが使えないないとき(p.135)
    • ThreadSafe?でないオブジェクトをInjectionしたい場合のこと。たとえば、Requestごとにつくられるオブジェクトは他のスレッドと共有されてはいけない。AOPを使うと書かれているのは、Springのルックアップメソッドインジェクションのことを指しているようだ。(この本が書かれたときはまだルックアップメソッドインジェクションはSpringになかったはずだが)
    • ロジックをはさんだ条件付の設定のこと。StarategyのFactoryを設定して、ロジックはFactoryに押し込めばよいとおもわれる。
    • BeanFactoryAware?の話。いいことか悪いことかは別にしてこういうことができる。
    • ???。4番目は何を言っているのかわからない。
  • IoC Containers
    • PicoContainer?はおもちゃみたい。
    • コードがコンパクトと言う意味ではPicoContainer?は学習に向いているかもしれないが、PicoContainer?でできることはSpringでもできる。PicoContainer?を使う積極的な理由はない。
    • IoC Container間では少ないコスト移行することができる。
    • SpringからSeaser2への設定ファイル変換ツールはつくることはできるか?可能だろうが意味があまりないだろう。Seasar2からEJB3ならば意味がある。Seasar2からSpringへの変換はOGNL式を使っている場合は難しい。
  • Portabilityにこだわりすぎてはいけない。
    • 実際問題コンテナを移行することはないだろう。
    • コンテナはビジネス要件には関わらない。
  • ドキュメントとチュートリアル
    • PicoContainer?のチュートリアルはわかりやすい。
    • Springのドキュメントは文章が多すぎる。第3者が書いたチュートリアルはわかりやすいものが多い。

7章 SpringFramework?の紹介


Spring概観1

  • BeanFactory?
    • Springの根本となるコンテナ。ただしSpringはコンテナと言う呼び方が嫌いらしいのでBeanFactory?という名前になっている。
    • Seasar2ではS2Container。
  • Application context
    • MessageやEventを扱うBeanFactory?。Webで使われる実装がある。Seasar2にはこれに相当するものはない。
    • ひがさん「MessageはWebのフレームワークが扱えばよい。Eventの管理をコンテナがするとコンテナ依存になる。そのためSeasar2にはない。]
  • Application contextという名前は大雑把過ぎるのではないか?
  • AOP framework
    • SpringもSeasar2もAOP Allianceに準拠している。
    • 有名じゃないAOP frameworkはみんな準拠している?
  • Auto-Proxying
    • 複数のコンポーネントに対してまとめてアスペクトをかけるときに使われる。AspectJもこのパターン。Seasar2にはない。だがあると便利なのでは。
    • ひがさん「どのコンポーネントに対してAspectがかかっているわかりにくくなるのがデメリット。複数のAspectを一つのコンポーネントにかけるときにアスペクトの順番が指定できない。もしSeasar2で用意するならば複数のアスペクトをひとつにまとめたスタックをコンポーネントに指定できるようにする。JBossにはそのようなものがある。
    • Springではアスペクトをかける順番指定できるはず。
    • SpringでAuto-Proxyingが必要とされるのはSpringのAOPがとても煩雑だからではないか。
  • Transaction management
    • 一般的なトランザクションとAPIを融合。Spring自前のトランザクションとJTA、JDBCと組み合わせている。
  • JDBC support
    • あるテンプレートを実装するとconnectionのopne/closeやResultSet?のopen/closeを自動で行ってくれる。
    • あまり使われていない。DBUtilsとは少し使い方が異なる。
    • Seasar2にはS2JDBCがある。
  • Integration with O/R mapping tools
    • Springは糊のような役割を担う。
  • Web MVC framework
    • Spring MVCを使っている人は見たことがない。独自のフレームワークと言える。
  • Remoting support
    • HessianやBurapやHttpなどいろんなプロトコルに対応している。
    • Seasar2では今のところSandBoxにHessianやBurap対応のものがある。ひがさん「将来的にはこれらを同じインタフェースで扱えるようにするつもり

Spring概観2 (J2EE)

  • J2EE一般
    • SpringではJNDIを使っていたとしても普通のBeanのように扱える。
    • Springではejb-jar.xmlを読み込んで処理ができるらしい。
    • コネクションプールについてはSpringはJakarta Commons DBCPを手厚くサポートしている。Jakarta Commons DBCPの弱点はトランザクションとの連携があまり考慮されていないこと。だがSpringはJakarta Commons DBCPに対してSpringのトランザクションと連携させるための処理をしている。
    • Seasar2は自前でコネクションプールの仕組みを持っている。Jakarta Commons DBCPを使おうとすると非常に扱いにくくなるので。Seasar2はDataSource?もJTAも特定の実装を期待していないけれども自前の実装をもつ。
    • JDBCについてSpringはSmartDataSource?というDataSource?をextendsしたインタフェースなどがありJDBCのトランザクションで使われている。
    • SpringのHibernateはHibernateのトランザクションとJTAなどを統合したもの。
  • Web Application Context
    • Web専用のApplication Context。
    • 設定の仕方はBeanFacotry?とほとんど変わらないはず。コンテナ(BeanFactory?)を階層化する設定ができる。
  • ContextLoaderListener?
    • Seasar2ではS2ContainerServlet?がこれに相当する。
    • Seasar2でなぜListenerでなくServletを使うのかと言うとGETリクエストで動作確認やリロードができて便利なため。
  • WebApplicationContextUtils?
    • ServletContext?に格納されているWebApplicationContext?を取得するのに使われる。

BeanFactory?の機能

  • 設定ファイルの書き方
    • Springのbeanタグにはidとnameとaliasを指定できる。
      • idはXMLのid型。DTDレベルでの検証がかけられるのがメリット。別のファイルにあるものについてはid使えない。XMLのid型であるため使えない文字もある。プレスホルダーはidに対して指定できない。
      • nameはただのNMTOKEN。別ファイルにあるものはnameで参照。
      • aliaseは何に使うか?
    • localという指定はまだできるのか?すべてglobalになった?
    • 3種類あるのはややこしくないか?Seasar2ではnameのみ1種類。
    • Springの特徴はBeanの参照の仕方。valueタグやrefタグを使う。PropertyEditor?がvalueタグのbodyをJavaのオブジェクトに変換する。
  • 設定ファイルのGUIサポート
    • Seasar2のキジムナー相当のものとしてSpringIDEがあるが貧弱な機能。
    • バージョンのサポートが1.0。ロッドとの連携がとれていないのでは?
    • BeanFactory?の継承をサポートするのが難しいのかもしれない
  • BeanFactory?
    • インタフェースからわかるようにSpringではコンポーネントをnameで参照する。
    • Classでの参照はBeanFactory?レベルではない。内部的にAutowiring時のbyTypeなどではclassで参照している。
    • BeanFactory?.getBean(String, Class)の2番目でClassが渡せるのは、キャスト可能かどうかをBeanFactory?でチェックできるようにするため。この機能はSeasar2では必要ない機能。Seasar2ではClassで取得するときほとんど。nameで取得するときにはキジムナーがチェックしてくれるのでこの機能は必要ない。
    • BeanFactory?にisSingleton()というメソッドがあるがこれはなぜここにあるのか。Seasar2でいうところのCompormentDef?のようなコンポーネントのメタデータを返すようにし、そこにSingletonかどうかの情報をもたせるべき。
    • 名称について
      • なぜcreateBean()ではなくgetBean()という名前なのか?Singletonを取得すると言う意味でgetを使っているのだろう。
      • Singletonを管理するのになぜBeanFactory?なのか?BeanRegistory?のほうが適切だと思う。HivemindはRegistoryという名前を使っている。
    • BeanFactory?は階層構造をもつことができる。自分のなかに見つからないときは親を探しにいき、なかったら例外となる。階層構造の考え方はSpringとSeasar2ではまったく異なる。Springは親の参照ができるが子供の参照はできない。Seasar2は子供とルートが参照できるが親の参照は出来ない。ロッド氏は細かいインタフェースをたくさん作ってそれらを階層化して使うのが好き。BeanFactory?の階層構造についてはkoichikさんが日記で説明してくれてます。http://d.hatena.ne.jp/koichik/20041215#1103133619
  • BeanFactory?でXMLの読み込み
    • *を使っての読み込みなどもできる。
    • 兄弟関係はあるのか?
    • 設定ファイルはXMLだけでなくプロパティファイルにも可能。Log4Jと似ている。だが利点はあるのか?
    • XMLでできることは手動でもできる。
    • SpringのXMLの解析はDOMを使っている。Seasar2はSAX。
    • Springのエラーログは横に長すぎ。
  • Singleton
    • Springではbeanタグのsingleton属性trueならばsingleton、falseならばprototypeとなる。
    • Seasar2でこれに相当するのはcomponentタグのinstance属性。singleton、prototype、outer、request、sessionなどがある。
    • SpringもThreadLocal?で管理するものを用意する案をもっているようだが、singletonという属性名ではうまくあらわせない。
  • Autowiring
    • Beanの参照をrefタグなどを使わずに自動で解決すること。Seasar2ではautoBindingと言う。
    • byType, byName, constuructor, auto-detect, noの5種類がある。
    • byType:プロパティの型とbeanの型で付き合わせる。
    • byName:プロパティの名前とbeanの名前で付き合わせる。曖昧でうまくいきそうもない。推奨されていない。
    • SpringのbyTypeでは実行時にコンテナをなめて必要なコンポーネント取得している。同じ型が複数登録されていた場合は例外が発生する。毎回コンテナをなめないようにキャッシュしているかもしれない。Seasar2の場合、同じ型が複数登録されていた場合、設定ファイルを読み込んだ時点でそれを把握している。そのため重複した型のコンポーネントが求められたらすぐに例外が発生する。
    • ロッド氏「Autowiringは大規模では使わず明示したほうが良い。
    • ひがさん「できるだけAutoBinding?を使ったほうが良い。人が設定すればするほどまちがいが多くなる。型による自動バインディングが楽でないと大規模の開発は難しい。
    • Seasar2ではInterfaceのときだけAutoBinding?なので基本的にはまちがわないはず。
    • SpringではintやStringなどの基本的な型を除いた実装クラスに対してもAutowiringできてしまう。
    • Seasar2のautoBindingはconstructorとproperty両方の混在OK。
  • Dependency check
    • XML読み込んだ時点であるコンポーネントがセットされているかどうかをチェックし、セットされていない場合に例外を発生させる機能。
    • セットが必須ならばコンストラクターインジェクションをしたほうがよい。セッターインジェクションで必須というのは中途半端。
    • Seasar2にはない。
    • Spring入門記では説明していない。
  • Lyfecycle
    • Singletonで管理されているBeanに対して初期化と破棄を行う。
    • このようなインタフェースは本来JDKでサポートして欲しい。コンポーネント作ったときに呼ばれるメソッドがあればいい。
    • Spring
      • インタフェースとXML定義の2種類でサポートしている。
      1. インタフェースとしてInitializingBean?DispozableBean?が用意されている。PicoContainer?やAvalonもこの方式。
      2. benaタグのinit-method属性とdestroy-method属性でメソッド名を指定する。引数があるものは呼び出させない。インタフェースを使うとSpringに依存するのであとからXMLの属性が追加されたのではないか?
    • Seasar2
      • initMethodタグとdestroyMethodタグで指定できる。
      • 任意のメソッドに任意の引数を渡して複数回呼べる。
      • Lifecycleの管理と言うよりもインジェクションを行うために用意された。たとえばコレクションに対するインジェクションなど。Springではコレクションをインジェクションできるようにlistタグやmapタグが用意されているが実装クラスがSpringに指定されるのがうれしくない。
      • ひがさん「DIにはコンストラクターインジェクションとセッターインジェクションだけでは十分ではない。任意のメソッドに任意の引数を渡してインジェクションできることが必要。そうすればJavaで組み立てられるものならば何でもできる。
  • BeanFactoryAware?
    • コンポーネントでBeanFactory?をプロパティに持ちたいときに使う。Bean名称とメソッド名と引数を受け取るコンポーネントがリモートから呼び出されたときにBeanFactory?に登録されているコンポーネントをリフレクションで呼び出すなど。BeanFactoryAware?を実装しておけばSpringが自動的にBeanFactory?をインジェクションしてくれる。
    • Seasar2ではこういうxxxAwareの類のインタフェースを使わない。S2Contanierもコンポーネントの1つとしてContainer自身に登録されているのでS2Contanierを受け取るSetterさえ用意すれば簡単にインジェクションされる。
  • factory-method属性
    • Spring1.1から新しくfactory-method属性というものが加わった。
    • たとえば次のようなJavaコード
      Hoge.getInstance() 
      は次のように表すことができる。
      <bean name="hoge" class="Hoge" factory-method="getInstance"> 
      Seasar2で同じことをするとOGNL式をつかって以下のようになる。
      <component name="hoge">@Hoge@getInstance()</component>
      OGNL式を定義すればいろいろできる。次のようなことも可能。SpringのJNDI系のFactoryがいらなくなる。
      <component name="context" class="javax.naming.InitialContext">
      <component name="hoge">context.lookup("java:comp/UserTransaction")</component>
  • Collectionのインジェクション
    • list、map、set、propsの4種類のタグが用意されている。Spring1.1からはネストも可能になった。
    • 実装はSpringで決められている。実装を切り替えたいならインジェクションされた先でnew LinkedList?(arg)とかするしかないのでは。
  • AOP
    • SpirngのAOPはデフォルトコンストラクターがないとうまく動かない。CGLIBを使うときにデフォルトコンストラクターが必要ということ。
    • 詳しくは次回の8章で。
  • FactoryBean?
    • getObjerct()というメソッドが一番重要。FactoryBean?.getObjerct()で取得したものを他のコンポーネントへDIできる。
    • SpringからSeasar2への移行で一番問題となるところがFactoryBean?FacBean?はOGNL式へ置き換えるのが一番早い。

ここまでわかっていれば明日からBeanFactory?が使えます。

Application Contextの機能

リソースにアクセスするのにコンテナに依存してしまうのはいいのだろうか?

  • MessageSource?
    • Webの場合、MessageSource?へのアクセスはWebのフレームワークにまかせるべき。
    • Velocityなどそういうものがないフレームワークに有効なのかもしれない。
    • バッチなどでメッセージをフォーマットしたいときにも使えるか。
  • File Resouce
    • パスを適切に変換する。
  • Callbackのためのインタフェース
    • BeanFactoryAware?と使い方は同じ。以下のようなものがある。
    • ApplicationContextAware?
    • ResourceLoaderAware?
    • ServletContextAware?
  • BeanFactoryPostProcessor?
    • コンテナの機能を拡張できる。
    • AutoProxy?もこれを使っている。Beanの定義に対してProxをかけている。
    • BeanFactoryPostProcessor?を実装したPropertyPlaceholderConfigurer?は設定ファイルの値をプロパティファイルから取得する。このようなプレースホルダーの機能はニーズが高い。
    • Seaser2ではOGNL式を使えば次のようにしてSpringのPropertyPlaceholderConfigurer?と同等のことがことが可能。
      <component name="prop" class="java.util.Properties">
        <initMethod name="load">
         <arg>@java.lang.Thread@currentThread()
           .getContextClassLoader()
           .getResourceAsStream("nt/seasar/prop/a.properties")
         </arg>
       </initMethod>
      </component>
      <component name="hoge" class="Hoge" >
        <arg>prop["foo"]</arg>
      </component>
      SeasarSandboxProjectにあるS2Textを使えばもっと簡単にプロパティファイルが扱える。

その他

  • Springの動作環境
    • コアの部分はspring-core.jarとcommons-logging.jarさえあれば動く。
    • Springは1.1.2ではJDK1.4に依存していたが1.1.3ではJDK1.3にも対応した。
  • Testについて
    • ロッド氏「単体テストにはコンテナつかわず、コードで書くべき。コンテナを使ってしまっては結合テストになる。
    • ひがさん「単体テストにもコンテナ使えばいい。コードで書くよりも設定ファイルを使ったほうが記述量が少なくてすむ(Seasar2はAutoBinding?の機能が発達しているので)。Seasar2ではS2UnitとMockInterseptor?を使ってMockObject?を用意するテストを推奨している。SpringのAOPはコードで書くのがつらいと思う。
    • SpringにはS2Unit相当のものがない。TSSでSpringのS2Unit相当のものを作っている人がいたが否定的な意見が多く寄せられていた。otsukaさんも作っていた。http://blog.ozacc.com/archives/000859.html
    • テストデータをExcelで用意することについて
      • テストデータをExcelに書けばユーザーさんに用意してもらうことも可能。
      • コードにテストデータを書くと正しいかどうかはプログラマにしかわからなくなってしまう。
    • FITやFITNESSEはつかえるか?便利そうだがコードを書くのが大変だ。
  • Hibernateについて
    • HibernateTemplate?の役割は何か。
      • 例外のハンドリング?
      • SessionFactory?からSessionをとるのを少し楽にするくらいの役割?
    • HibernateDaoSupport?
      • HibernateTemplate?を使った実装
    • S2Hibernate
      • Hibernateはコネクションプールについてもトランザクションについても独自のインタフェースをもっている。そのインタフェースを実装すればJTAとも任意のコネクションプールとも連動できるが、S2Hibernateはそのどちらも使っていない。S2HibernateはHibernateのコネクションプーリングとトランザクションは使わずJ2EEのDataSource?TransactionManager?を使っている。HibernateはSQLを実行するぐらいしかしていない。
      • S2HibernateとSpringのHibernateは実装がかなり違う。SpringはHibernateの機能をたくさん使っている。
      • Hibernate自身にトランザクションやデータソースの機能はいらない。O/Rマッピングだけに専念してほしい。
      • S2HibernateはOrpenSessionView?をサポートしている。Filterの入出でTransaction開始終了が行われる。
    • OrpenSessionView?
      • ロッド氏は280ページあたりでOrpenSessionView?を気をつけて使えと言っている。
      • OrpenSessionView?はJ2EEパターンのDispather Viewに近いといえる。
      • HibernateでOrpenSessionView?を使う理由はLazyLoading?をしたいから
      • OrpenSessionView?を使いたいくない理由は、層で役割を完了させなければいけないと考えた場合、データのアクセスはデータアクセス層で完了させなければいけないにもかかわらず、OrpenSessionView?を使うとWeb層でもデータにアクセスすることになるから。web.xmlに指定したerrorページには飛ばすことはできるが、例外がおきたときの処理ができない(もう一段フィルターをかければロジックを実行することも可能なのかもしれない)。


次回について

  • 8章(宮本さん)
  • 9章(未定)

この議事録を読んで分からないことや、疑問に思ったこと、その他ご意見等がありましたら下記コメント欄にお願いします。匿名でも結構です。

  • Spring MVCがあまり使われていないのは、日本語による紹介記事が少ないのと取っつきにくいからだと考えております。 -- 竹本 浩? 2008-03-01 (土) 19:51:10
  • 私のホームページ(http://www.pwv.co.jp/~take/TakeWiki/)にSpring-MVCの紹介記事を載せましたので参考にしてください。 -- 竹本 浩? 2008-03-01 (土) 19:53:44