2007-03-23

[Gain] Extend transaction boundaries to business layer with Spring 2.0 AOP

一般的架構為web -> Business -> Dao,合理的transaction boundaries應該要放在Business上,畢竟commit/rollback unit應該是一次Business operation,而不僅僅只是一次dao operation。
但使用Hibernate或沒有container的架構中,transaction不是來自Hibernate session就是JDBC connection(事實上是同一個啦),所以若要將transaction boundaries延伸到Business Layer,勢必變成Business Layer會看到Hibernate session,這又是我們不願意見到的。
但有了Spring AOP之後,這問題似乎可以解決了。
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="load*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
<!-- SystemService -->
<tx:method name="login" propagation="REQUIRED" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allServiceMethods" expression="execution(* com.xxx.service.*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"/>
</aop:config>

首先,透過allServiceMethods規範所有的Business Layer method都必須經過txAdvice定義的transactionManager。
<aop:pointcut id="allServiceMethods" expression="execution(* com.xxx.service.*Service.*(..))"/>表示在com.xxx.service這個package下名稱為Service結尾的所有class的所有method。
<tx:advice id="txAdvice" transaction-manager="transactionManager">...</tx:advice>定義了以method name為規則的transaction條件。
最後用<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"/>將上面兩項綁起來。

沒有留言:

張貼留言