【Java Web】013 -- SpringBootWeb综合案例(事务管理、AOP)
目录
一、事务管理
1、事务回顾
①、概念与操作
2、Spring事务管理(@Transactional)
①、案例:解散部门(删除部门,同时删除该部门下的员工)
②、@Transactional注解
③、开启事务管理日志开关(application.yml)
3、事务进阶(@Transactional注解的两个属性)
①、rollbackFor
②、propagation(传播行为)
③、案例:解散部门时,记录操作日志到数据库表中
④、小结
二、AOP基础
1、AOP概述
2、AOP快速入门
①、入门案例
②、AOP应用场景与优势
③、小结
3、AOP核心概念
①、连接点:JoinPoint
②、通知:Advice
③、切入点:PointCut
④、切面:Aspect
⑤、目标对象:Target
⑥、AOP执行流程
⑦、小结
三、AOP进阶
1、通知类型
①、通知类型示例
②、@PointCut注解:抽取公共切点表达式
③、小结
2、通知顺序
①、类名字母排序
②、@Order注解加在切面类上控制顺序
3、切入点表达式
①、切入点表达式 - execution
②、如何通过一个切入点表达式,来描述两个方法呢?
③、execution表达式 -- 小结
④、切点表达式 -- @annotation
⑤、小结
4、连接点
四、AOP案例
1、案例介绍
2、思路分析
3、实现步骤
一、事务管理
1、事务回顾
①、概念与操作
2、Spring事务管理(@Transactional)
①、案例:解散部门(删除部门,同时删除该部门下的员工)
正常示例:
Ⅰ、在EmpMapper.java中添加删除部门员工方法: |
|
Ⅱ、在EmpService中添加方法: |
Service实现类: |
异常示例:
我们通过@Transactional注解可以完成对事务的控制,从而将删除部门和删除部门下员工这两个操作划分到一个事务中来,即要么同时成功,要么同时失败。
②、@Transactional注解
我们直接在ServiceImpl中的方法上加上@Transactional注解即可
③、开启事务管理日志开关(application.yml)
3、事务进阶(@Transactional注解的两个属性)
默认情况下,只有出现运行时异常,才会回滚异常,如果不是,则不会回滚,那么我们可以通过rollbackFor来指定控制的异常类型,从而实现非运行时异常的回滚。
①、rollbackFor
示例:
在ServiceImpl方法的@Transactional上指定异常的类型:
②、propagation(传播行为)
③、案例:解散部门时,记录操作日志到数据库表中
IDEA控制台日志过滤插件:
示例:
Ⅰ、准备好日志记录表(dept_log): |
|
Ⅱ、修改DeptServiceImpl.java: |
|
Ⅲ、添加DeptLogMapper方法: |
这里的delete方法与insert方法共用一个事务: Mapper方法:
|
Ⅳ、为了完成案例需求,我们应该将insert方法的propagation属性设为 REQUIRES_NEW: |
这样就使得insert方法会新创建一个事务,而不加入已有的delete事务中 |
④、小结
二、AOP基础
1、AOP概述
我们可以将业务方法抽取成模板方法:
而这种模板方法的实现方法就是:动态代理
2、AOP快速入门
①、入门案例
示例:
Ⅰ、导入依赖: |
|
Ⅱ、编写AOP程序: |
@Aspect注解:用来标识当前类是一个AOP类 |
Ⅲ、运行测试: |
|
②、AOP应用场景与优势
③、小结
3、AOP核心概念
①、连接点:JoinPoint
可以被AOP控制的方法(暗含方法执行时的相关信息),连接点指的是可以被aop控制的方法。例如:入门程序当中所有的业务方法都是可以被aop控制的方法。 |
在SpringAOP提供的JoinPoint当中,封装了连接点方法在执行时的相关信息。 |
②、通知:Advice
通知,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)。
在入门程序中是需要统计各个业务方法的执行耗时的,此时我们就需要在这些业务方法运行开始之前,先记录这个方法运行的开始时间,在每一个业务方法运行结束的时候,再来记录这个方法运行的结束时间。 但是在AOP面向切面编程当中,我们只需要将这部分重复的代码逻辑抽取出来单独定义。抽取出来的这一部分重复的逻辑,也就是共性的功能。 |
|
③、切入点:PointCut
切入点,匹配连接点的条件,通知仅会在切入点方法执行时被应用 在通知当中,我们所定义的共性功能到底要应用在哪些方法上?此时就涉及到了切入点pointcut概念。切入点指的是匹配连接点的条件。通知仅会在切入点方法运行时才会被应用。 在aop的开发当中,我们通常会通过一个切入点表达式来描述切入点(后面会有详解) |
假如:切入点表达式改为DeptServiceImpl.list(),此时就代表仅仅只有list这一个方法是切入点。只有list()方法在运行的时候才会应用通知。 |
④、切面:Aspect
切面,描述通知与切入点的对应关系(通知+切入点) 当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作。 |
切面所在的类,我们一般称为切面类(被@Aspect注解标识的类) |
⑤、目标对象:Target
目标对象指的就是通知所应用的对象,我们就称之为目标对象。 |
|
⑥、AOP执行流程
Spring的AOP底层是基于动态代理技术来实现的,也就是说在程序运行的时候,会自动的基于动态代理技术为目标对象生成一个对应的代理对象。在代理对象当中就会对目标对象当中的原始方法进行功能的增强。
⑦、小结
三、AOP进阶
1、通知类型
注意事项:(@Around环绕通知)
①、通知类型示例
示例:
@Before:前置通知,在目标方法前被执行 |
|
@Around:环绕通知,在目标方法前、后都被执行 |
|
@After:后置通知,在目标方法后被执行 |
|
@AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行 |
|
@AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行 |
|
②、@PointCut注解:抽取公共切点表达式
解决大量重复的切入点表达式:(抽取) |
如果切入点表达式需要改动,那么只需要改动最上面的就可以了 |
③、小结
@AfterReturning与@AfterThrowing注解互斥,返回后通知,有异常不会执行;异常后通知,只有异常时才会通知
2、通知顺序
①、类名字母排序
通知顺序与类名有关:
类名越靠前,前置通知则越先执行,后置通知则越后执行
②、@Order注解加在切面类上控制顺序
3、切入点表达式
①、切入点表达式 - execution
示例: |
全类名不建议省略,因为一旦省略,这个范围就有些过大,从而影响效率
|
通配符:
示例: |
*:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数
|
..:多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数 |
②、如何通过一个切入点表达式,来描述两个方法呢?
我们可以一个一个来描述: |
|
③、execution表达式 -- 小结
书写建议:
④、切点表达式 -- @annotation
示例:
通过@annotation表达式来简化切入点表达式描述多个方法的操作: |
Ⅰ、创建一个自定义注解: |
|
Ⅱ、给想切入的方法上加上注解: |
|
Ⅲ、编写切入点表达式: |
|
⑤、小结
4、连接点
示例:@Around通知
运行结果:
四、AOP案例
1、案例介绍
2、思路分析
@annotation解决目标方法匹配:
3、实现步骤
示例:
Ⅰ、引入AOP起步依赖: |
|
Ⅱ、导入数据库表,引入对应的实体类 |
创建操作日志表(operate_log): 引入实体类(OperateLog):
|
Ⅲ、引入Mapper接口: |
OperateLogMapper:
|
Ⅳ、自定义Log注解,仅起到标识方法的作用,不需要指定属性: |
anno: |
Ⅴ、定义一个切面类: |
LogAspect: 代码实现细节: 获取request对象,从请求头中获取到jwt令牌,解析令牌获取出当前用户的id。 |
Ⅵ、启动服务、进行测试: |
数据库表数据:(增、删、改)
|