目次へ

7. トランザクション管理 2

2005.09.20 株式会社四次元データ 木虎直樹

7.1. BeanNameAutoProxyCreator による宣言的トランザクション管理

前章で org.springframework.transaction.interceptor.TransactionProxyFactoryBean を使用して宣言的トランザクション管理を行うことができるようになりましたが同様の設定を行いたいにもかかわらず Facade や DAO となるクラスごとにトランザクションの振る舞いなどを設定するのは煩雑です。そのような際に便利なクラスが Spring には用意されています。org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator です。このクラスを使用すれば、たとえば指定したクラスの "update" で始まるメソッドには、トランザクションの振る舞いとしてすべて PROPAGATION_REQUIRED を指定するというようなことが簡単にできるようになります。BeanNameAutoProxyCreator で設定しなければならないプロパティは以下の 2つです。

  • interceptorNames
  • beanNames

beanNames はその名前からわかりますが、トランザクション管理対象となる Bean の名前を指定します。interceptorNames には org.aopalliance.intercept.Interceptor を実装したクラスを指定します。AOP を学習していない今は、トランザクション管理を行うには Bean 定義ファイルで設定した org.springframework.transaction.interceptor.TransactionInterceptor の名前を指定するということを理解するだけで十分です。その TransactionInterceptor ですが、以下のプロパティを指定する必要があります。

  • transactionManager
  • transactionAttributeSource

transactionManager については前章で出てきたため説明の必要はないでしょう。transactionAttributeSource には org.springframework.transaction.interceptor.TransactionAttributeSource を実装したクラスを指定します。 TransactionAttributeSource はどのクラスのどのメソッドにどのようなトランザクション管理を行うのかを指定します。TransactionAttributeSource の具象クラスには以下の 3つのクラスのうちいずれかを指定します。

  • org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource
  • org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource
  • org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource
MatchAlwaysTransactionAttributeSource
すべてのメソッドを transactionAttribute プロパティで指定された属性に基づきトランザクショナルに実行します。 以下の使用例ではトランザクション属性に PROPAGATION_REQUIRED を指定しています (実はデフォルトで PROPAGATION_REQUIRED が適用されます)。
<bean id="txAttribute"

      class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
  <property name="transactionAttribute"><value>PROPAGATION_REQUIRED</value></property>
</bean>
NameMatchTransactionAttributeSource
指定された名前を持つメソッドを指定された属性に基づきトランザクショナルに実行します。メソッド名とトランザクション属性は java.util.Properties 型の properties プロパティで指定します。前章で説明した org.springframework.transaction.interceptor.TransactionProxyFactoryBean と同様にキーとなる値にメソッド名を、キーに対応する値にトランザクション属性を指定します。メソッド名にワイルドカード "*" を使用することもできます。 以下の使用例では insert で始まるメソッドにはトランザクション属性として PROPAGATION_REQUIRED を指定し、それ以外の文字列で始まるメソッドには PROPAGATION_REQUIRED,readOnly を指定しています。
<bean id="txAttribute"

      class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
  <property name="properties">
    <props>
      <prop key="insert*">PROPAGATION_REQUIRED</prop>

      <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
    </props>
  </property>
</bean>
MatchAlwaysTransactionAttributeSource
指定されたクラスの指定された名前を持つメソッドを指定された属性に基づきトランザクショナルに実行します。クラス名とメソッド名、トランザクション属性は java.util.Map 型の methodMap プロパティで指定します。Map のキー値に完全限定名で指定したクラス名とメソッド名を "." ドットでつないだ値を指定します。メソッド名には NameMatchTransactionAttributeSource と同様ワイルドカード "*" を使用することができます。Map のキーに対応する値にトランザクション属性を指定します。 以下の使用例では com.techscore.spring.PersonManager クラスの insert で始まるメソッドにはトランザクション属性として PROPAGATION_REQUIRED を指定し、com.techscore.spring.PersonManager クラスのそれ以外の文字列で始まるメソッドには PROPAGATION_REQUIRED,readOnly を指定しています。
<bean id="txAttribute"
      class="org.springframework.transaction.interceptor.MethodMapTransactionAttributeSource">
  <property name="methodMap">
    <map>

      <entry key="com.techscore.spring.PersonManager.insert*">
        <value>PROPAGATION_REQUIRED</value>
      </entry>
      <entry key="com.techscore.spring.PersonManager.*">
        <value>PROPAGATION_REQUIRED,readOnly</value>

      </entry>
    </map>
  </property>
</bean>

最後に

<beans>
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
     ...(略)...
  </bean>

  <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource"><ref local="dataSource"/></property>
  </bean>

  <bean id="txAttribute"
        class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
    <property name="transactionAttribute"><value>PROPAGATION_REQUIRED</value></property>
  </bean>

  <bean id="txInterceptor"
        class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="transactionAttributeSource"><ref bean="txAttribute"/></property>

  </bean>
  <bean id="debug"
        class="org.springframework.aop.interceptor.DebugInterceptor"/>
  <bean id="autoProxyCreator"
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

    <property name="interceptorNames">
      <list>
        <value>txInterceptor</value>
        <value>debug</value>

      </list>
    </property>
    <property name="beanNames">
      <list>
        <value>personManager</value>

        <value>companyManager</value>
      </list>
    </property>
  </bean>
  <bean id="personManager" class="com.techscore.spring.PersonManagerImpl">

     ...(略)...
  </bean>
  <bean id="companyManager" class="com.techscore.spring.CompanyManagerImpl">
     ...(略)...
  </bean>

</beans>

BeanNameAutoProxyCreator の interceptorNames, beanNames プロパティを指定するときに ref 要素を使用していないことに注意してください。Bean をコンテナから取り出すには以下のようにします。

PersonManager manager = (PersonManager) context.getBean("personManager");

実習課題 1

6章の実習課題 1 を改良しなさい。

  • org.springframework.transaction.interceptor.TransactionProxyFactoryBean を使用すること

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp