当前位置:   article > 正文

Spring事务管理——AOP配置_spring aop配置 advice transaction-manager

spring aop配置 advice transaction-manager

说明

平时学习Spring很少用到AOP这个功能,不过这个功能对Spring事务管理有一定的作用。发现真正在用的时候自己配环境的情况特别少,都是在别人配好环境的情况下就开始用了。所以更加要记录一下配置环境的过程啊。这里用一个转账实例来说明。

Spring事务管理

事务管理一般涉及到三个顶级接口,分别是PlatformTransactionManager(事务管理器),TransactionDefinition(事务详情),TransactionStatus(事务状态)。进行事务配置时,必须要配置事务管理器和事务详情。而事务状态是Spring底层用来进行相应操作的。

事务

开始之前说一下事务吧。这里有一点简单的介绍,可以看一下,这里要再说一下。事务状态和事务详情就不说了,可以查一下。这里主要说一下传播行为,比较常用的记录一下,不常用的不说了。
传播行为主要是指两个业务之间如何共享事务
例如转账的时候,先要从一个账户出账,然后另一个账户入账,这就可以看成是两个业务。传播行为常用的主要有下面几种:

required:必须
支持当前事务,A如果有事务,B将使用该事务,如果A没有事务,B将创建一个新的事务
supports:支持
支持当前事务,A如果有事务,B将使用该事务,如果A没有事务,B将以非事务执行
requires_new:必须新的
如果A有事务,将A的事务挂起,B创建一个新的事务,如果A没有事务,B创建一个新事务
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

事务管理器

我们比较常用的事务管理器一般有两种,分别是DataSourceTransactionManager和HibernateTransactionManager。

  • DataSourceTransactionManager:jdbc开发时的事务管理器,采用jdbcTemplate
  • HibernateTransactionManager:hibernate开发时用的事务管理器

这里用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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述
除了这个之外,我们还要新建一个项目,待会方便直接使用
jar包
在这里插入图片描述
目录
在这里插入图片描述
都是比较基础的代码,直接贴出来就好。

interface AccountDao

package com.shanmu.dao;

public interface AccountDao {

	public void out(String outer,Integer money);
	public void in(String inner,Integer money);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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);
		
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

interface AccountService

package com.shanmu.service;

public interface AccountService {

	/**
	 * 转账
	 * @param outer
	 * @param inner
	 * @param money
	 */
	public void transfer(String outer,String inner,Integer money);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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);
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这里的xml文件还没有给出,下面主要来看怎么加入事务了。

AOP配置事务——基于xml

指的是在Spring的xml文件中进行配置aop,自动生成代理,从而进行事务的管理,步骤如下:

  1. 配置事务管理器
  2. 配置事务详情
  3. 配置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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

运行结果
在这里插入图片描述
看一下数据库
在这里插入图片描述

AOP配置事务——基于注解

步骤是:

  1. 配置事务管理器,并将事务管理器交于Spring
  2. 在目标类或目标方法中添加注释即可@Transactional

所以,首先在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" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

然后在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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/995154
推荐阅读
相关标签
  

闽ICP备14008679号