Aop简要概述:
Aop面向切面编程,可以实现代码的解耦合,提高代码的复用性。
1:切面:
切面的意思通俗的意思就是切入的代码,比如开启事务方法的代码,提交事务的代码
2:切入点:
需要切入代码的地方,比如待执行代码的前,或者后
3:连接点
满足规则的地方,定位到某个类,或者方法
4:通知
通知分为:前置通知,后置通知,环绕通知,异常通知
spring实现事务控制代码:
一:引入依赖(为了方便起见,使用springboot2版本,懒得再去一个一个引入依赖信息)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
二:配置application.yml文件
server:
port: 8080 #服务器端口号
spring:
jpa:
database: mysql #使用 jpa
show-sql: true
datasource:
driver-class-name: com.mysql.jdbc.Driver 数据库驱动
username: root 用户名
password: 1234 密码
url: jdbc:mysql://localhost:3306/clouddb01?useUnicode=true&characterEncoding=UTF8 数据库地址
三:创建启动类
package com.zbin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动类
*
* @author zhangbin 2019年03月22日
* @version 1.0
* @since 1.0 2019年03月22日
*/
@SpringBootApplication
public class AopApplication {
public static void main(String[] args) {
SpringApplication.run(AopApplication.class,args);
}
}
至此,该项目可以正常启动了
四:创建工具类,用于开启事务,提交事务,会滚事务
package com.zbin.aop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
//注入spring容器中
@Component
//创建为多例对象,放置多线程安全问题
@Scope("prototype")
public class AopAspectUtil {
@Autowired
private DataSourceTransactionManager manager; //注入spring的事务管理器
//事务拦截器
private TransactionStatus transaction;
/**
* @return org.springframework.transaction.TransactionStatus
* @Author zhangbin
* @Description 开启事务
* @Date 9:54 2019/3/25
* @Param []
**/
public TransactionStatus begin() {
transaction = manager.getTransaction(new DefaultTransactionAttribute());//设置为默认事务隔离级别
//返回事务拦截器
return transaction;
}
/**
* @return void
* @Author zhangbin
* @Description 提交事务
* @Date 9:54 2019/3/25
* @Param []
**/
public void commit() {
// 提交事务
manager.commit(transaction);
}
/**
* @return void
* @Author zhangbin
* @Description 会滚事务
* @Date 9:54 2019/3/25
* @Param []
**/
public void rollback() {
//回滚事务
manager.rollback(transaction);
}
}
五:定义注解
package com.zbin.aop.mytransation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})//设置注解使用范围
@Retention(RetentionPolicy.RUNTIME)//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
public @interface MyTransactional {
}
六:自定义通知
使用注意,在针对事务管理方面,方法中不要去try{}catch(){},使用try,,catch后aop不能获取到异常信息,会导致出现异常后不能进行回滚,如果确实需要try,,,catch 可以再finally中加上TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();由此段代码进行事务的回滚
package com.zbin.aop.transaction;
import com.zbin.aop.mytransation.TransactionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
@Component
@Aspect
public class AopTransaction {
@Autowired
private TransactionUtils transactionUtils;
@Around("execution(* com.zbin.aop.service.UserService.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//调用方法之前执行
System.out.println("开启事务");
transactionUtils.begin();
proceedingJoinPoint.proceed();
//调用方法之后执行
System.out.println("提交事务");
transactionUtils.commit();
}
@AfterThrowing("execution(* com.zbin.aop.service.UserService.add(..))")
public void afterThrowing() {
System.out.println("异常通知 ");
//获取当前事务进行回滚
//TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
transactionUtils.rollBack();
}
}
七:测试效果 ,,自行测试
@MyTransactional
public void add() {
userDao.add("test001", 20);
int i = 1 / 0;
System.out.println("---------------------");
userDao.add("test002", 20);
}