目录
1、首先,导入相关依赖(以下依赖是整合了ssm的所有依赖,所以可以直接复制使用)
2、引入 Spring 事务相关依赖后,在 Spring MVC 中有两种(XML 配置和注解)驱动 Spring 事务的方式
3、接着,你可以使用 @Transactional 注解标注在方法(或者类)上面,使得方法的执行处于一个事务中
Spring AOP定义:
Spring AOP(Aspect-Oriented Programming)是Spring框架提供的一种面向切面编程的解决方案。AOP是一种编程范式,它可以从横向的切面来组织和管理程序逻辑,从而实现代码的重用和复合性的提高。Spring AOP通过在运行时动态地将切面织入到程序中,实现了对代码的横向切面管理,提高了代码的可重用性、可维护性和可扩展性。
Spring AOP的实现原理:
- 切面(Aspect): 切面是一个横切关注点的模块化单元,它包含了通知和切点。通知是在切点上执行的代码,用于实现横切关注点的功能,如日志记录、性能监控等。切点是指在应用程序中定义的一组连接点,通知将在这些连接点上执行。
- 代理: Spring AOP使用代理来实现切面功能。当一个Bean被代理时,Spring创建一个代理对象,该对象拦截了Bean的方法调用,并在方法调用前后执行通知。
- 织入(Weaving): 织入是将切面与应用程序的目标对象关联起来的过程。Spring支持编译时织入、运行时织入和加载时织入三种织入方式。
- 通知类型: Spring AOP支持五种通知类型:前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。每种通知类型在不同的切点执行时机触发。
- 实现原理: Spring AOP的实现原理主要基于动态代理和字节码增强。Spring使用动态代理来创建代理对象,并使用字节码增强技术在运行时修改类的字节码,以实现切面功能。具体实现方式包括JDK动态代理和CGLIB动态代理两种。
Spring AOP 支持以下常见的切面功能:
- 前置通知(Before advice):在目标方法调用之前执行的操作。
- 后置通知(After advice):在目标方法调用之后执行的操作,无论是否发生异常。
- 返回通知(After returning advice):在目标方法成功返回结果后执行的操作。
- 异常通知(After throwing advice):在目标方法抛出异常后执行的操作。
- 环绕通知(Around advice):包围目标方法调用,可以在调用前后执行自定义操作(需要进行返回)
Spring 事务的传播级别:
- REQUIRED:默认传播级别,如果正处于一个事务中,则加入;否则,创建一个事务
- SUPPORTS:如果正处于一个事务中,则加入;否则,不使用事务
- MANDATORY:如果当前正处于一个事务中,则加入;否则,抛出异常
- REQUIRES_NEW:无论如何都会创建一个新的事务,如果正处于一个事务中,会先挂起,然后创建
- NOT_SUPPORTED:不使用事务,如果正处于一个事务中,则挂起,不使用事务
- NEVER:不使用事务,如果正处于一个事务中,则抛出异常
- NESTED:嵌套事务,如果正处于一个事务中,则创建一个事务嵌套在其中(MySQL 采用 SAVEPOINT 保护点实现的);否则,创建一个事务
创建一个事物步骤:
1、首先,导入相关依赖(以下依赖是整合了ssm的所有依赖,所以可以直接复制使用)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--文件下载-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>compile</scope>
</dependency>
</dependencies>
2、引入 Spring 事务相关依赖后,在 Spring MVC 中有两种(XML 配置和注解)驱动 Spring 事务的方式
a、接下来,我们先使用xml格式来配置事物
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- 定义一个数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">...</bean>
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 指定数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务模块驱动,指定使用上面定义事务管理器,默认值为 transactionManager -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
b、使用配置类的方式,需要在 Spring 能扫描的一个 Bean 上添加一个@EnableTransactionManagement 注解,然后添加一个事物类,并在spring配置当中使用Import注解导入配置类
文件部分结构:(将JdbcConfig文件使用注解的方式配置在SpringConfig中)
package com.yinan.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
public class JdbcConfig {
private String username="root";
private final String password="123456";
private final String url="jdbc:mysql://localhost:3306/product";
private final String driver="com.mysql.cj.jdbc.Driver";
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
// 添加事物
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
package com.yinan.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;
//配置spring
@Configuration
@ComponentScan(value="com.yinan.service")
@Import({JdbcConfig.class, MybatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
3、接着,你可以使用 @Transactional 注解标注在方法(或者类)上面,使得方法的执行处于一个事务中
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
public void update(){
try {
// 数据库操作
} catch (Exeception e){
// 将事务状态设置为回滚
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
}
}