一、事务管理
Transactional注释
Transactional注解的两个常见属性
属性值 | 含义 |
---|---|
REQUIRED(默认)
|
【默认值】需要事务,有则加入,无则创建新事务
|
REQUIRES_NEW
|
需要新事务,无论有无,总是创建新事务
|
二、AOP
AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白
核心概念
![](https://img-blog.csdnimg.cn/direct/49fb403025744f09ab3042f217f4258f.png)
五个通知类型
@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
@Before:前置通知,此注解标注的通知方法在目标方法前被执行
@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行 @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行 @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行
注:
@Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行
@Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值。
注解@PointCut
该注解的作用是将公共的切点表达式抽取出来,需要用到时引用该切点表达式即可。
通知顺序
1、不同切面类中,默认按照切面类的类名字母排序:
目标方法前的通知方法:字母排名靠前的先执行
目标方法后的通知方法:字母排名靠前的后执行
2、用 @Order(数字) 加在切面类上来控制顺序:
目标方法前的通知方法:数字小的先执行
目标方法后的通知方法:数字小的后执行
切入点表达式
execution
execution( 访问修饰符 ? 返回值 包名 . 类名 .? 方法名 ( 方法参数 ) throws 异常 ?)
annotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@MyLog //自定义注解(表示:当前方法属于目标方法)
public List<Dept> list() {
List<Dept> deptList = deptMapper.list();
return deptList;
}
@MyLog //自定义注解(表示:当前方法属于目标方法)
public void delete(Integer id) {
//1. 删除部门
deptMapper.delete(id);
}
public void save(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.save(dept);
}
}
3、定义切面类:
@Slf4j
@Component
@Aspect
public class MyAspect6 {
//针对list方法、delete方法进行前置通知和后置通知
//前置通知
@Before("@annotation(AOPProject.anno.MyLog)")//(括号里是自己定义的注释的路径,我这里的AOPProject包的上一级是java包,也就是从java包的下一级开始)
public void before(){
log.info("MyAspect6 -> before ...");
}
//后置通知
@After("@annotation(AOPProject.anno.MyLog)")
public void after(){
log.info("MyAspect6 -> after ...");
}
}
连接点
在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。 对于 @Around 通知,获取连接点信息只能使用 ProceedingJoinPoint。
@Around("execution(* com.itheima.service.DeptService.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
String className = joinPoint.getTarget().getClass().getName(); //获取目标类名
Signature signature = joinPoint.getSignature(); //获取目标方法签名
String methodName = joinPoint.getSignature().getName(); //获取目标方法名
Object[] args = joinPoint.getArgs(); //获取目标方法运行参数
Object res = joinPoint.proceed(); //执行原始方法,获取返回值(环绕通知)
return res;
}
@Before("execution(* com.itheima.service.DeptService.*(..))")
public void before(JoinPoint joinPoint) {
String className = joinPoint.getTarget().getClass().getName(); //获取目标类名
Signature signature = joinPoint.getSignature(); //获取目标方法签名
String methodName = joinPoint.getSignature().getName(); //获取目标方法名
Object[] args = joinPoint.getArgs(); //获取目标方法运行参数
}