一、Spring对事务的管理方式
Spring通常使用以下三种方式实现对事务的管理
1、使用Spring的 事务代理工厂 管理事务;
2、使用Spring的 事务注解 管理事务;
3、使用 AspectJ的AOP 配置管理事务。
二、Spring事务管理API
Spring的事务管理,主要用到两个事务相关的接口。
1、事务管理器接口
事务管理器是 PlatformTransactionManager 接口对象。主要用于完成事务的提交、回滚 以及获取事务的状态信息。
A、常用的两个实现类:
PlatformTransactionManager 接口有两个常用的实现类:
DataSourceTransactionManager : 使用JDBC或iBatis进行持久化数据时使用;
HibernateTransactionManager : 使用Hibernate 进行持久化数据时使用。
B、Spring的回滚方式
Spring事务的默认回滚方式是:发生运行时异常时回滚,发生受查异常时提交,不过,对于受查异常,也可以手工设置其回滚方式。
2、事务定义接口:
事务定义接口 TransactionDefinition 中定义了事务描述相关的三类常量:
事务隔离级别、事务传播行为、事务默认超时时限、以及对他们的操作。
三、Demo
事务一般多用于对数据库的操作,所以想配置好数据库文件,当前以SpringMVC项目,IDE是eclipse。
jdbc.properties 中配置数据库的连接,每种数据库连接的驱动不一样,这里是MYSQL。
# MySQL
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mytestdb?useUnicode=true&characterEncoding=gbk
jdbc.username=root
jdbc.password=root
使用的spring-config.xml文件中用到的xsd约束如下图:

配置好后在spring-config.xml中添加加载jdbc.properties文件的配置,添加数据源配置,
<!-- 注册JDBC属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 注册数据源 -->
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
案例一、使用 Spring的事务代理工厂管理事务:
事务代理使用的类是 TransactionProxyFactoryBean ,该类需要初始化如下一些属性:
transactionManager : 事务管理器
target : 目标对象,即Service实现类对象
transactionAttributes : 事务属性设置
对于XML配置代理方式实现事务管理时,受查异常的回滚方式,程序员可以通过以下方式进行设置。
通过“-异常”方式,可使发生指定的异常时事务回滚;通过“+异常”方式,可使发生指定的异常时事务提交。
这个方法管理事务配置比较繁琐。
spring-cpnfig.xml文件中注册dao和service的bean对象,添加代理事务的配置
<!-- 注册Dao -->
<bean id="accountDao" class="com.transaction.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="stockDao" class="com.transaction.dao.impl.StockDaoImpl">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 注册Service -->
<bean id="stockService" class="com.transaction.service.StockProcessServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="stockDao" ref="stockDao"/>
</bean>
<!-- 注册事务管理器,三种管理方式都需要事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 生成事务代理 用事务代理工厂处理事务-->
<bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="myTxManager"/>
<property name="target" ref="stockService"/>
<property name="transactionAttributes">
<props>
<!-- key值service中要使用事务的方法名或其正则,中间就是事务的隔离级别和传播级别-->
<prop key="open*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
<prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-StockException</prop>
</props>
</property>
</bean>
此时使用 事务代理工厂管理事务配置完成,使用stockServiceProxy实例调用open开头的方法和buyStock方法会有事务管理,出现异常会事务回滚,代码在后面打包,稍安勿躁。
案例二、使用 SpringAOP 注解管理事务
说白了这个是直接在对应方法上添加事务注解 @Transactional(isolation=Isolation.DEFAULT, propagation=Propagation.REQUIRED)
这个方法配置简单,但是如果添加事务的方法太多的话,不太好管理。
并且配置隔离级别和传播级别。
现在先在spring-config.xml中添加事务配置,开启SpringAOP事务
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 开启注解驱动 可以使用SpringAOP设置事务 -->
<tx:annotation-driven transaction-manager="myTxManager"/>
如此便是配置好了SpringAOP事务配置,下面就是在方法中使用注解例子

案例三、使用 Spring AspectJ 管理事务
基于AspectJ配置文件,同一在一个地方配置事务,不会担心哪个需要配置事务的地方被漏掉。
下面就是spring-config.xml中的配置
<!-- 事务 -->
<!-- 注册事务管理器 -->
<bean id="myTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<!-- 使用AspectJ 设置事务 -->
<!-- 注册事务通知 -->
<tx:advice id="txAdvice" transaction-manager="myTxManager" >
<tx:attributes>
<!--
propagation :事物传播行为
isolation :事物隔离级别
read-only :只读
rollback-for :发生哪些异常回滚
no-rollback-for :发生哪些异常不回滚
timeout :过期信息
-->
<!-- 指定在连接点方法上应用的事务属性 -->
<tx:method name="open*" isolation="DEFAULT" propagation="REQUIRED" />
<tx:method name="buyStock" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException" />
</tx:attributes>
</tx:advice>
<!-- AOP配置 -->
<aop:config>
<!-- 指定切入点 -->
<aop:pointcut id="stockPointCut" expression="execution(* com.transaction.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="stockPointCut" />
</aop:config>
配置完成,这个其实还可以直接开启注解模式,使用注解来使用Aspect管理事务。
<!-- 开启aop 使用AspectJ去管理事务 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
四、AOP相关术语
通知:通知定义了切面是什么时候以及何时使用的概念,Spring切面有五类通知
前置通知(Before):在目标方法被调用之前调用通知功能。
后置通知(After):在目标方法完成之后调用通知,此时不关心方法的输出结果。
返回通知(After-returning):在目标方法成功执行之后调用通知。
异常通知(After-throwing):在目标方法抛出异常之后调用通知。
环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
连接点:是在应用执行过程中能够插入切面的一个点。
切点:切点定义了切面在何处要织入一个或者多个连接点。
切面:是通知和切点的结合,通知和切点共同定义了切面的全部内容。
引入:引入允许我们向现有类添加新方法或属性。
织入:是把切面应用到目标对象,并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期中有多个点可以进行织入:
编译期:在目标类编译时,切面被织入。这种方式需要特殊的编译器,AspectJ的织入编译器就是以这种方式织入切面的。
类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(class loader)它可以在目标类呗引入应用之前增强该目标类的字节码。
运行期:切面在应用运行到某个时刻时被织入,一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。SpringAOP就是以这种方式织入切面的。
项目地址: https://github.com/helloX007/springtransaction.git
本文介绍了Spring框架中的三种事务管理方式:使用Spring的事务代理工厂、使用Spring的事务注解以及使用AspectJ的AOP配置。文章详细阐述了每种方式的具体配置步骤及使用场景,并对AOP相关术语进行了说明。
1万+

被折叠的 条评论
为什么被折叠?



