spring声明式事务策略 aop拦截-学习笔记

本文介绍了Spring框架中的声明式事务管理机制,详细解释了其实现原理,并对比了与EJBCMT的不同之处。同时,文章还展示了如何通过XML配置文件进行具体的事务策略配置。

声明式事务管理:

Spring提供了声明式事务管理。是通过Spring AOP实现的。

Spring中进行事务管理的通常方式是利用AOP(面向切片编程)的方式,为普通java类封装事务控制,它是通过动态代理实现的,由于接口是延迟实例化的,spring的在这段时间内通过拦截器,加载事务切片。原理就是这样的,可以参考JDK动态代理实例。

Spring中进行事务控制:

动态代理的一个重要特征是,它是针对接口的,所以我们的DAO要通过动态代理来让spring接管事务,就必须在dao前面抽象出一个接口,当然如果没有这样的接口,那么spring会使用CGLIB来决解问题,但这不是spring推荐的方式。

大多数spring用户选择声明式事务管理。这是最少影响应用代码的选择,因而这是和非侵入性的轻量级容器的观念是一致的。

从考虑EJB CMT和spring声明式事务管理的相似以及不同之处出发是很有益的。他们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上下文调用setRollbackOnly()方法。不同之处如下:

1、不像EJB CMT绑定在JTA上,spring声明式事务管理可以在任何环境下使用。只需要更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作。

2、spring可以使声明式事务管理应用到普通的Java对象,不仅仅是特殊的类,如EJB。

3、spring提供声明式回滚规则:EJB诶呦地域的特征,回滚可以声明式控制,不仅仅是编程式的。

4、spring允许你通过AOP定制事务行为。如:如果需要,可以在事务回滚中插入定制的行为。也可以增加任意的通知,就像事务通知一样。使用EJB CMT,除了使用setRollbackOnly(),你没有办法能够影响容器的事务管理。

5、spring不提供高端应用服务器的跨越远程调用的事务上下文传播。如果你需要这些特征,推荐你使用EJB。然而,不要轻易使用这些特性。通常我们并不希望事务跨越远程调用。


回滚规则的概念:他们使得我们可以指定哪些异常应该发起自动回滚。我们在配置文件中,而不是Java代码中,以声明的方式指定。因此,虽然我们仍然可以编程调用TransactionStatus对象的setRollbackOnly()方法来回滚当前事务,多数时候我们可以指定规则,如MyApplicationException应用导致回滚。这有明显的优点,业务对象不需要依赖事务基础设施。例如:通常不需要引入任何Spring API,事务或其他任何东西。

EJB的默认行为是遇到系统异常(通常是运行是异常),EJB容器自动回滚事务。EJB CMT遇到应用程序异常(除了java.rmi.RemoteExcepiton外的checked异常)是不需要自动回滚事务。虽然Spring声明式事务管理沿用EJB的约定(遇到unchecked异常自动回滚事务),但是这是可以定制的。

Spring声明式事务管理的性能要胜过EJB CMT。

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xmlns:tx="http://www.springframework.org/schema/tx"  
  7.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  8.             http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  9.             http://www.springframework.org/schema/context   
  10.             http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  11.             http://www.springframework.org/schema/aop   
  12.             http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
  13.             http://www.springframework.org/schema/tx   
  14.             http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
  15.       
  16.       
  17.     <!-- 配置数据库驱动 -->  
  18.     <!-- <context:property-placeholder location="classpath:jdbc.properties"/> -->  
  19.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  20.         <property name="locations">  
  21.             <list>  
  22.                 <value>classpath:init.properties</value>  
  23.             </list>  
  24.         </property>  
  25.     </bean>  
  26.       
  27.     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  28.         <property name="driverClassName" value="${datasource.driverClassName}"/>  
  29.         <property name="url" value="${datasource.url}"/>  
  30.         <property name="username" value="${datasource.username}"/>  
  31.         <property name="password" value="${datasource.password}"/>  
  32.         <!-- 连接池启动是的初始值 -->  
  33.         <property name="initialSize" value="${datasource.initialSize}"/>  
  34.         <!-- 连接池的最大值 -->  
  35.         <property name="maxActive" value="${datasource.maxActive}"/>  
  36.         <!-- 最大空闲值、当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->  
  37.         <property name="maxIdle" value="${datasource.maxIdle}"/>  
  38.         <!-- 最小空闲值,当空闲的连接数少于阀值时,连接池就会预申请去一些连接、以免洪峰来时来不及申请 -->  
  39.         <property name="minIdle" value="${datasource.minIdle}"/>  
  40.     </bean>  
  41.     <!-- 配置hibernateSessionFactory -->  
  42.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  43.         <property name="dataSource" ref="dataSource" />  
  44.         <!-- <property name="mappingResources">  
  45.             <list>  
  46.                 <value>com/sample/domain/Person.hbm.xml</value>  
  47.             </list>  
  48.         </property> -->  
  49.         <property name="mappingDirectoryLocations">  
  50.             <list>  
  51.                 <!-- 采用属性注入com/sample/domain包下所有hbm.xml加载进来 -->  
  52.                 <value>classpath:com/sample/admin/domain</value>  
  53.             </list>  
  54.         </property>  
  55.         <property name="hibernateProperties">  
  56.             <value>  
  57.                 hibernate.dialect=${hibernate.dialect}  
  58.                 hibernate.hbm2ddl.auto=${hibernate.hbm2ddl.auto}  
  59.                 hibernate.show_sql=${hibernate.show_sql}  
  60.                 hibernate.format_sql=${hibernate.format_sql}  
  61.                 hibernate.cache.use_second_level_cache=${hibernate.cache.use_second_level_cache}  
  62.                 hibernate.cache.use_query_cache=${hibernate.cache.use_query_cache}  
  63.                 hibernate.cache.provider_class=${hibernate.cache.provider_class}  
  64.             </value>  
  65.             <!-- 另外一种写法 -->  
  66.             <!-- <props>  
  67.                 <prop key="hibernate.dialect">${hibernate.dialect}</prop>  
  68.             </props> -->  
  69.         </property>  
  70.     </bean>  
  71.       
  72.     <!-- 配置事务管理器 -->  
  73.     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  74.         <property name="sessionFactory" ref="sessionFactory" />  
  75.     </bean>  
  76.       
  77.     <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">  
  78.         <property name="sessionFactory" ref="sessionFactory" />  
  79.     </bean>  
  80.       
  81.     <!-- 延时加载问题解决OpenSessionInViewInterceptor 和 OpenSessionInViewFilter的配置  
  82.     在没有使用Spring提供的Open Session In View情况下,因需要在service(or Dao)层里把session关闭,  
  83.     所以lazy loading 为true的话,要在应用层内把关系集合都初始化,  
  84.     如 company.getEmployees(),否则Hibernate抛session already closed Exception -->  
  85.       
  86.     <bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">  
  87.         <property name="sessionFactory">  
  88.             <ref bean="sessionFactory"/>  
  89.         </property>  
  90.     </bean>  
  91.     <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  92.         <property name="interceptors">  
  93.             <list>  
  94.                 <ref bean="openSessionInViewInterceptor"/>  
  95.             </list>  
  96.         </property>  
  97.     </bean>  
  98.       
  99.     <!-- 事务策略配置管理器  
  100.     PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。spring默认的事务策略   
  101.     PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。   
  102.     PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。   
  103.     PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。   
  104.     PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。   
  105.     PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。   
  106.     PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。   
  107.     -Exception表示有Exception抛出时,事务回滚. -代表回滚+就代表提交   
  108.     readonly 就是read only, 设置操作权限为只读,一般用于查询的方法,优化作用.   
  109.       
  110.     设置强制使用CGLIB生成代理(spring代理方式 另外一种 JDKProxy动态代理)   
  111.     <property name="optimize" value="true" />   
  112.      -->  
  113.       
  114.     <!-- <bean id="baseTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">  
  115.         <property name="transactionManager" ref="transactionManager" />  
  116.         <property name="proxyTargetClass" value="true"/>  
  117.         <property name="transactionAttributes">  
  118.             <props>  
  119.                 <prop key="get*">PROPAGATION_NOT_SUPPORTED,readOnly</prop>  
  120.                 <prop key="find*">PROPAGATION_NOT_SUPPORTED,readOnly</prop>  
  121.                 <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>  
  122.                 <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>    
  123.                 <prop key="read*">PROPAGATION_REQUIRED,readOnly</prop>  
  124.                 <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>  
  125.                 <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>  
  126.                 <prop key="create*">PROPAGATION_REQUIRED,-Exception</prop>  
  127.                 <prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>  
  128.                 <prop key="modify*">PROPAGATION_REQUIRED,-Exception</prop>  
  129.                 <prop key="change*">PROPAGATION_REQUIRED,-Exception</prop>  
  130.                 <prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>  
  131.                 <prop key="remove*">PROPAGATION_REQUIRED,-Exception</prop>  
  132.                 <prop key="*">PROPAGATION_REQUIRED,-Exception</prop>  
  133.             </props>  
  134.         </property>  
  135.         <property name="optimize" value="true" />    
  136.     </bean> -->  
  137.       
  138.     <!-- 采用AOP拦截的方式实现事务管理 -->  
  139.     <aop:config proxy-target-class="true">  
  140.         <aop:pointcut id="transacationPointcut" expression="execution(* com.sample.admin.service..*.*(..))"/>  
  141.         <aop:advisor advice-ref="txAdvisor" pointcut-ref="transacationPointcut"/>  
  142.     </aop:config>  
  143.     <tx:advice id="txAdvisor" transaction-manager="transactionManager">  
  144.         <tx:attributes>  
  145.             <tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>  
  146.             <tx:method name="find*" read-only="true" propagation="NOT_SUPPORTED"/>  
  147.             <tx:method name="query*" read-only="true" propagation="NOT_SUPPORTED"/>  
  148.             <tx:method name="read*" read-only="true" propagation="NOT_SUPPORTED"/>  
  149.             <tx:method name="load*" read-only="true" propagation="REQUIRED"/>  
  150.             <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>  
  151.             <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>  
  152.             <tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/>  
  153.             <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>  
  154.             <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/>  
  155.             <tx:method name="change*" propagation="REQUIRED" rollback-for="Exception"/>  
  156.             <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>  
  157.             <tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception"/>  
  158.             <tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>  
  159.         </tx:attributes>  
  160.     </tx:advice>  
  161.     <!-- 采用注解方式配置 打开 -->  
  162.     <!-- <tx:annotation-driven transaction-manager="transactionManager" />-->  
  163. </beans> 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值