(感谢您的关注和点赞支持!)
Spring-test
在前面测试中,每次从spring 容器中获取 bean 都需要实例化 ApplicationContext ,相对麻烦,可以考虑使用 Spring-test 完成测试
Spring Test 是 Spring Framework 提供的一系列测试支持工具,它为开发者提供了在单元测试和集成测试中模拟 Spring 上下文、依赖注入(DI)和事务管理的能力
添加依赖
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
</dependency>
编写测试类
在 src/test/java 下
编写测试类
需要使用 注解 @SpringJUnitConfig
xml 方式:
@SpringJUnitConfig(locations = "classpath:spring.xml") public class SpringTestJunit5{ }
注解方式:
@SpringJUnitConfig(SpringTestJunit5.class) @ComponentScan("com.wdzl.anno") public class SpringTestJunit5{ } 如果是全注解,则@SpringJUnitConfig 传入配置扫描注解的类
测试配中配置依赖
SpringTestJunit5
@SpringJUnitConfig(locations = "classpath:spring.xml")
public class SpringTestJunit {
@Autowired
private EmpService empService;
@Test
public void test(){
}
}
全注解方式:
@SpringJUnitConfig(SpringTestJunit5.class)
@ComponentScan("com.wdzl.anno")
public class SpringTestJunit5 {
@Autowired
private BookService bookService;
@Test
public void testAOP(){
bookService.save();
}
}
三、声明式事务
声明式事务(declarative transaction management)是Spring提供的对程序事务管理的方式之一。 Spring的声明式事务顾名思义就是采用声明的方式来处理事务
编写转账业务代码
package com.wdzl.service;
import com.wdzl.dao.IEmpDao;
import com.wdzl.pojo.Emp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class EmpService {
@Autowired
private IEmpDao empDao;
public Emp get(Integer empno){
return empDao.get(empno);
}
public List<Emp> queryAll(){
return empDao.queryAll();
}
public void save(Emp emp){
empDao.save(emp);
}
public void update(Emp emp){
empDao.update(emp);
}
/**
* 转账
* @param fromId 转出账号
* @param toId 转入账号
* @param money 转账金额
*/
public void trans(Integer fromId,Integer toId,Float money){
Emp fromEmp = get(fromId);
Emp toEmp = get(toId);
//内存修改
fromEmp.setSalary(fromEmp.getSalary()-money);
toEmp.setSalary(toEmp.getSalary()+money);
// 持久化
empDao.update(fromEmp);
//假设异常
// "".substring(9999);
empDao.update(toEmp);
}
}
写好后,正常测试,看是否在没有异常时能正常转账;
异常时,部分转账;出现不一致情况,并没回滚。
配置事务
两种常用方式
- xml 配置
- 注解
xml 配置方式
只需在spring 配置文件中修改
1. 配置事务管理器
依赖数据源,通过控制数据源来完成事务控制
<!--1. 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2 . 配置 advice
注意:在idea中,配置 tx 命名空间时方法,敲入 <tx:advice> 自动提示,但是一定要注意,选择 tx 的命名空间,
不要选择 cache !!!!!!!!!
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="tra*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
- propagation 事务的传播行为:
- REQUIRED : 必须在事务中,如果方法执行时,已经在事务中,则继续使用当前事务;如果没有事务,则重新打开新的事务
- SUPPORTS : 支持当前事务状态,如果在事务中,则执行当前事务。如果没有,不会新开启事务
- REQUIRES_NEW : 每次都会重新开启新的事务
3. aop 配置
<aop:config>
<aop:pointcut id="xx" expression="execution(public * com.wdzl.service..*.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="xx"/>
</aop:config>
注意:上面配置,需要注入前面的 advice 和 切入点 id
4. 测试
通过上面配置,不需要修改任何代码的,直接正常测试调用就可以了
@SpringJUnitConfig(locations = "classpath:spring.xml")
public class SpringTestJunit {
@Autowired
private EmpService empService;
@Test
public void test(){
empService.trans(1,2,500);
}
}
注解配置方式
1. 配置事务管理器
在 spring.xml 中配置
<!--1. 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2. 开启声明式事务注解
<!--2.启用声明式事务注解-->
<tx:annotation-driven/>
3. 方法标注注解
在需要事务支持的方法标注注解 @Transactional
@Transactional
/**
* 转账
* @param fromId 转出账号
* @param toId 转入账号
* @param money 转账金额
*/
public void trans(Integer fromId,Integer toId,Float money){
Emp fromEmp = get(fromId);
Emp toEmp = get(toId);
//内存修改
fromEmp.setSalary(fromEmp.getSalary()-money);
toEmp.setSalary(toEmp.getSalary()+money);
// 持久化
empDao.update(fromEmp);
//假设异常
// "".substring(9999);
empDao.update(toEmp);
}
}
4. 测试
@SpringJUnitConfig(SpringTestJunit5.class)
@ComponentScan("com.wdzl.anno")
public class SpringTestJunit5 {
@Autowired
private EmpService empService;
@Test
public void testAOP(){
empService.trans(1,2,500);
}
}