这两天学到事务管理这一块,结合到之前的terasoluna框架,觉得书本上讲的还是简单阿。我就把我从书本上学到的再结合实际的项目以及网上看到的一些内容,对声明式事务管理做个整理吧。
我看得Spring in Action第二版中只提到了用TransactionProxyFactoryBean和<tx:advice/>,定义注释驱动这三种,我承认后两种的内容很好,很强大。但是实际的项目当中可能不会这么用。尤其是定义注释驱动。个人觉得把下面两种弄明白就可以了。
下面这个配置是要用到的。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="DataSource"/> </property> </bean>
其实不管你用哪种事务管理器,都要把transactionManager注入到Spring容器中。这里我用的是JDBC事务。如果你用Hibernate事务,或者JPA/JDO/JTA都是差不多的。
第一种:TransactionProxyFactoryBean,学过AOP的都知道,切面注入是用ProxyFactoryBean注入的。同样,事务管理也是一个切面,这里框架提供了TransactionProxyFactoryBean来注入。
代码如下:
<bean id="fundServiceDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 配置事务管理器 --> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 此属性指定目标类本省是否是代理的对象,如果目标类没有实现任何类,就设为true代表自己 --> <property name="proxyTargetClass"> <value>false</value> </property> <property name="proxyInterfaces"> <value>com.jack.fund.service.IFundService</value> </property> <!-- 目标bean --> <property name="target"> <ref bean="fundService" /> </property> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
以下可能还有其他的xxxServiceDAOProxy.大家可以看出针对每一个功能模块配置一个业务代理服务。如果模块多大话,就显得代码有点多了,发现他们只是稍微一点不一样。这时我们就应该想到继承的思想。
代码如下:
<!-- 利用继承的思想简化配置,要把abstract="true" --> <bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true"> <!-- 配置事务管理器 --> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
而具体的模块可以简单的这样配置。只要指明它的parent(父类)就可以了。父类一般把abstract="true",因为在容器加载的时候不需要初始化,等到用的时候再有它的子类调用的时候,再去初始化。
<bean id="fundServiceDAOProxy" parent="transactionBase" > <property name="target"> <ref bean="fundService" /> </property> </bean>
这样配置的话,如果有多个像fundService这样模块时,可以少些很多重复的代码。
第二种:主要利用BeanNameAutoProxyCreator自动创建事务代理。
代码如下:
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 配置事务属性 --> <property name="transactionAttributes"> <props> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>fundService</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean> 这种方法主要利用了拦截器的原理。 如果系统中模块过多的话,可以采用下面这种 <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <!-- 自动代理 --> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!-- 可以是Service或DAO层(最好是针对业务层*Service) --> <property name="beanNames"> <list> <value>*Service</value> </list> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> </list> </property> </bean>
自动代理还有一种用法就是结合正规表达式和advice使用。
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" /> <bean id="regexpMethodPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref bean="transactionInterceptor" /> </property> <property name="pattern"> <value>.*</value> </property> </bean>
更多详细信息请查看 Spring 教程 http://www.itchm.com/forum-59-1.html