Spring事务管理
@Transactional注解
- 位置:业务层(Service)的方法上、类上、接口上。
- 作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务。
rollbackFor属性
- 默认情况下,只有出现 RuntimeException 才回滚异常。rollbackFor属性用于控制出现何种异常类型时回滚事务。
@Transactional(rollbackFor = Exception.class)
propagation属性
- 事务传播行为:当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。
- REQUIRED:大部分情况下都是用该传播行为。
- REQUIRES_NEW:当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。
SpringAOP
AOP概述
- Aspect Oriented Programming(面向切面编程),其实就是面向特定方法编程。将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来。
- 实现:Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy去创建代理对象;而对于没有实现接口的对象,Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理。
- 使用场景:操作记录日志、权限控制、事务管理······
- 优势:代码无侵入、减少重复代码、提高开发效率、维护方便······
AOP核心概念
AOP通知
-
通知类型:
@Before
(前置通知):目标对象的方法调用之前触发。@After
(后置通知):目标对象的方法调用之后触发。@AfterReturning
(返回通知):目标对象的方法调用完成,在返回结果值之后触发。@AfterThrowing
(异常通知):目标对象的方法运行中抛出 / 触发异常后触发。@Around
(环绕通知):编程式控制目标对象的方法调用。环绕通知是所有通知类型中可操作范围最大的一种,因为它可以直接拿到目标对象,以及要执行的方法,所以环绕通知可以任意的在目标对象的方法调用前后搞事,甚至不调用目标对象的方法。
-
注意:
@Around
环绕通知需要自己调用ProceedingJoinPoint.proceed()
来让原始方法执行,其他通知不需要考虑目标方法执行。@Around
环绕通知方法的返回值,必须指定为0bject,来接收原始方法的返回值。@PointCut
注解的作用是将公共的切点表达式抽取出来,需要用到时引用该切点表达式即可。@AfterReturning
和@AfterThrowing
两者互斥。如果方法调用成功无异常,则会有返回值;如果方法抛出了异常,则不会有返回值。
-
通知顺序:当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行。
- 不同切面类中,默认按照切面类的类名字母排序。
- 目标方法前的通知方法:字母排名靠前的先执行。
- 目标方法后的通知方法:字母排名靠前的后执行。
- 用
@Order(数字)
加在切面类上来控制顺序。- 目标方法前的通知方法:数字小的先执行。
- 目标方法后的通知方法:数字小的后执行。
- 不同切面类中,默认按照切面类的类名字母排序。
切入点表达式
- 描述切入点方法的一种表达式。
- 主要用来决定项目中的哪些方法需要加入通知。
execution(...)
切入点表达式:根据方法的签名来匹配。
- 注意:
- 根据业务需要,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式。
- 所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都以 find 开头,更新类方法都以 update开头。
- 描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性。
- 在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名匹配尽量不使用…,使用*匹配单个包。
@annotation(...)
切入点表达式:匹配标识有特定注解的方法。
连接点
- 在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
- 对于@Around通知,获取连接点信息只能使用 ProceedingJoinPoint。
- 对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint 的父类型。