赞
踩
平时学习Spring很少用到AOP这个功能,不过这个功能对Spring事务管理有一定的作用。发现真正在用的时候自己配环境的情况特别少,都是在别人配好环境的情况下就开始用了。所以更加要记录一下配置环境的过程啊。这里用一个转账实例来说明。
事务管理一般涉及到三个顶级接口,分别是PlatformTransactionManager(事务管理器),TransactionDefinition(事务详情),TransactionStatus(事务状态)。进行事务配置时,必须要配置事务管理器和事务详情。而事务状态是Spring底层用来进行相应操作的。
开始之前说一下事务吧。这里有一点简单的介绍,可以看一下,这里要再说一下。事务状态和事务详情就不说了,可以查一下。这里主要说一下传播行为,比较常用的记录一下,不常用的不说了。
传播行为主要是指两个业务之间如何共享事务
例如转账的时候,先要从一个账户出账,然后另一个账户入账,这就可以看成是两个业务。传播行为常用的主要有下面几种:
required:必须
支持当前事务,A如果有事务,B将使用该事务,如果A没有事务,B将创建一个新的事务
supports:支持
支持当前事务,A如果有事务,B将使用该事务,如果A没有事务,B将以非事务执行
requires_new:必须新的
如果A有事务,将A的事务挂起,B创建一个新的事务,如果A没有事务,B创建一个新事务
我们比较常用的事务管理器一般有两种,分别是DataSourceTransactionManager和HibernateTransactionManager。
这里用DataSourceTransactionManager来说明
下面是一些准备工作,我们需要数据库中的数据,所以这里新建一个数据库
create database 数据库名;
use 数据库名;
create table account(
id int primary key auto_increment,
username varchar(50),
money int(20)
);
insert into account values(null,"jack",10000);
insert into account values(null,"rose",10000);
除了这个之外,我们还要新建一个项目,待会方便直接使用
jar包
目录
都是比较基础的代码,直接贴出来就好。
interface AccountDao
package com.shanmu.dao;
public interface AccountDao {
public void out(String outer,Integer money);
public void in(String inner,Integer money);
}
class AccountDaoImpl
package com.shanmu.daoimpl; import org.springframework.jdbc.core.support.JdbcDaoSupport; import com.shanmu.dao.AccountDao; public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{ @Override public void out(String outer, Integer money) { this.getJdbcTemplate().update("update account set money = money -? where username = ?",money,outer); } @Override public void in(String inner, Integer money) { this.getJdbcTemplate().update("update account set money = money +? where username = ?",money,inner); } }
interface AccountService
package com.shanmu.service;
public interface AccountService {
/**
* 转账
* @param outer
* @param inner
* @param money
*/
public void transfer(String outer,String inner,Integer money);
}
class AccountServiceImpl
package com.shanmu.serviceimpl; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import com.shanmu.dao.AccountDao; import com.shanmu.service.AccountService; public class AccountServiceImpl implements AccountService { //由Spring注入 private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override //这里是转账的方法,调用dao public void transfer(String outer, String inner, Integer money) { accountDao.out(outer, money); /* 这里是测试事务的语句,当int i=1/0没有注释的时候会产生异常,如果没进行事务管理, 则只会出账,不会进账,总钱数少了1000,如果进行了事务管理,则会回滚,不会提交, 这样原本的账户不会发生变化。 */ //int i=1/0; accountDao.in(inner, money); } }
class TestApp
package com.shanmu; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.shanmu.service.AccountService; public class TestApp { @Test public void demo01(){ String xmlPath="applicationContext.xml"; ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath); AccountService accountService=(AccountService)applicationContext.getBean("accountService"); accountService.transfer("jack", "rose", 1000); } }
这里的xml文件还没有给出,下面主要来看怎么加入事务了。
指的是在Spring的xml文件中进行配置aop,自动生成代理,从而进行事务的管理,步骤如下:
看一下配置文件(applicationContext.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" 是配置事务详情要用到的 --> <!-- 1 dataSource --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/数据库名"></property> <property name="user" value="root"></property> <property name="password" value="密码"></property> </bean> <!-- 2 dao --> <bean name="accountDao" class="com.shanmu.daoimpl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 3 service --> <bean name="accountService" class="com.shanmu.serviceimpl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <!-- 4事务管理 --> <!-- 4.1 事务管理器 --> <bean name="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 4.2 事务详情(事务通知),在aop筛选基础上,对ABC三个确定使用什么样的事务。 <tx:attributes>用于配置事务详情(事务属性) <tx:method name=""/>详情具体配置 propagation 传播行为 isolation 隔离级别 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <!-- 这里传播行为默认为required --> <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/> </tx:attributes> </tx:advice> <!-- 4.3 AOP编程,目标类有ABCD(4个连接点),切入点表达式 确定增强的连接器,从而获得切入点:ABC --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.shanmu.serviceimpl.*.*(..))"/> </aop:config>
运行结果
看一下数据库
步骤是:
所以,首先在applicationContext.xml文件中配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 1 dataSource --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/数据库名"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 2 dao --> <bean name="accountDao" class="com.shanmu.daoimpl.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 3 service --> <bean name="accountService" class="com.shanmu.serviceimpl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> <!-- <property name="transactionTemplate" ref="transactionTemplate"></property> --> </bean> <!-- 4 事务管理 --> <!-- 4.1 事务管理器 --> <bean name="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 4.2 将管理器交于spring * transaction-manager 配置事务管理器 * proxy-target-class 默认是false 若为true,底层强制使用cglib代理 --> <tx:annotation-driven transaction-manager="txManager" />
然后在transfer方法上加上注解
package com.shanmu.serviceimpl; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import com.shanmu.dao.AccountDao; import com.shanmu.service.AccountService; public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override @Transactional //@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT) //给类加上该注解,则该类中所有方法执行事务,给方法上加注解,则该方法执行事务 public void transfer(String outer, String inner, Integer money) { accountDao.out(outer, money); /* 这里是测试事务的语句,当int i=1/0没有注释的时候会产生异常,如果没进行事务管理, 则只会出账,不会进账,总钱数少了1000,如果进行了事务管理,则会回滚,不会提交, 这样原本的账户不会发生变化。 */ //int i=1/0; accountDao.in(inner, money); } } ```java 这里会发现没有配事务详情,其实@Transactional注解可以写成下面的形式,这样就可以在括号中配置事务详情 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191116202146442.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hhbnNtdQ==,size_16,color_FFFFFF,t_70) **结果** ![在这里插入图片描述](https://img-blog.csdnimg.cn/20191116202435116.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。