TransactionAttributeSource、 TransactionAttribute


在TransactionProxyFactoryBean上有setTransactionAttributeSource()與setTransactionAttributes()方法,它們是用來設定交易屬性的策略實例。

org.springframework.transaction.interceptor.TransactionAttributeSource介面 上有一個getTransactionAttribute()方法,您可以根據傳遞給它的Method實例與Class實例,決定該返回一個什麼內容的 org.springframework.transaction.interceptor.TransactionAttribute實例,一個最簡單 的TransactionAttributeSource實作是 org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource, 對於每一個方法呼叫都會應用交易,它會返回的TransactionAttribute實例之預設傳播行為是PROPAGATION_REQUIRED, 隔離層級為ISOLATION_DEFAULE。

一個應用的例子如下所示:
...
<bean id="transactionAttributeSource"
      class="org.springframework.transaction.interceptor.
            → MatchAlwaysTransactionAttributeSource"/>

<bean id="userDAOProxy"
      class="org.springframework.transaction.
            → interceptor.TransactionProxyFactoryBean">
    <property name="proxyInterfaces">
        <list>
            <value>onlyfun.caterpillar.IUserDAO</value>
        </list>
    </property>
    <property name="target">
        <ref bean="userDAO"/>
    </property>
    <property name="transactionManager">
        <ref bean="transactionManager"/>
    </property>
    <property name="transactionAttributeSource">
        <ref bean="transactionAttributeSource"/>
    </property>
</bean>
...


您可以使用org.springframework.transaction.interceptor.DefaultTransactionAttribute,並設置自己的交易策略,之後將之設定給TransactionAttributeSource,例如:
...
<bean id="myTransactionAttribute"
      class="org.springframework.transaction.
         → interceptor.DefaultTransactionAttribute">
    <property name="propagationBehaviorName">
        <value>PROPAGATION_REQUIRES_NEW</value>
        </property>
    <property name="isolationLevelName">
        <value>ISOLATION_REPEATABLE_READ</value>
    </property>
</bean>

<bean id="transactionAttributeSource"
      class="org.springframework.transaction.
      → interceptor.MatchAlwaysTransactionAttributeSource">
    <property name="transactionAttribute">
        <ref bean="myTransactionAttribute"/>
    </property>
</bean>

<bean id="userDAOProxy"
      class="org.springframework.transaction.
            → interceptor.TransactionProxyFactoryBean">
    <property name="proxyInterfaces">
        <list>
            <value>onlyfun.caterpillar.IUserDAO</value>
        </list>
    </property>
    <property name="target">
        <ref bean="userDAO"/>
    </property>
    <property name="transactionManager">
        <ref bean="transactionManager"/>
    </property>
    <property name="transactionAttributeSource">
        <ref bean="transactionAttributeSource"/>
    </property>
</bean>
...


可以使用org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource來指定某些方法要應用交易,以及要應用的交易策略,例如:
...
<bean id="transactionAttributeSource"
      class="org.springframework.transaction.
        → interceptor.NameMatchTransactionAttributeSource">
    <property name="properties">
        <props>
            <prop key="insert*">
                PROPAGATION_REQUIRES_NEW
            </prop>
        </props>
    </property>
</bean>

<bean id="userDAOProxy"
      class="org.springframework.transaction.
          → interceptor.TransactionProxyFactoryBean">
    <property name="proxyInterfaces">
        <list>
            <value>onlyfun.caterpillar.IUserDAO</value>
        </list>
    </property>
    <property name="target">
        <ref bean="userDAO"/>
    </property>
    <property name="transactionManager">
        <ref bean="transactionManager"/>
    </property>
    <property name="transactionAttributeSource">
        <ref bean="transactionAttributeSource"/>
    </property>
</bean>
...

在NameMatchTransactionAttributeSource的"properties"屬性上,可以指定方法名稱與交易策略,方法名稱的 指定可以指定全名,也可以使用Wildcard來指定,例如上面的指定中,只要方法名稱以insert為開頭的都會應用相對應的交易策略。

在指定交易策略時,指定的格式如下:
傳播行為,隔離層級,唯讀,+例外, -例外

除了傳播行為一定要設置之外,其它都可選擇性的設置,中間以逗號區隔,例如:
PROPAGATION_REQUIRED,readOnly,-MyCheckedException

MyCheckedException前面加上"-"時,表示發生指定例外時撤消操作,如果前面加上"+",表示發生例外時立即提交。

在比較簡單的設置中,可以僅設置TransactionProxyFactoryBean,並在它的"transactionAttributes"屬性上直接設置要應用交易的方法及交易策略,例如:
...
<bean id="userDAOProxy"
      class="org.springframework.transaction.
          → interceptor.TransactionProxyFactoryBean">
    <property name="proxyInterfaces">
        <list>
            <value>onlyfun.caterpillar.IUserDAO</value>
        </list>
    </property>
    <property name="target">
        <ref bean="userDAO"/>
    </property>
    <property name="transactionManager">
        <ref bean="transactionManager"/>
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="insert*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>
...


您甚至也可以直接指定TransactionInterceptor,以獲得更多的控制,例如:
...
<bean id="transactionInterceptor"
      class="org.springframework.transaction.
              → interceptor.TransactionInterceptor">
    <property name="transactionManager">
        <ref bean="transactionManager"/>
    </property>
    <property name="transactionAttributeSource">
        <value>
 onlyfun.caterpillar.UserDAO.insert*=PROPAGATION_REQUIRED
        </value>
    </property>
</bean>

<bean id="userDAOProxy"
      class="org.springframework.aop.
          → framework.ProxyFactoryBean">
    <property name="proxyInterfaces">
        <list>
            <value>onlyfun.caterpillar.IUserDAO</value>
        </list>
    </property>
    <property name="target">
        <ref bean="userDAO"/>
    </property>
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
</bean>
...

選擇哪一種設定方式是需求的問題,您可以嘗試在DeclarativeTransactionDemo專案的Bean 定義檔上設定以上所介紹的方式,基於篇幅的限制,以上僅列出部份的設定內容。