spring Aop与事务 笔记

Aop 的简介与作用

1.Aop其实就是面向切面编程 与面向对象编程(Oop) 一样就是一种编程范式

其作用就是:在不惊动原始设计的基础上为其进行功能增强。简单的说就是在不改变方法源代码的基础上对方法进行功能增强。

spring 理念:无入侵试/无侵入式

 

Aop其中核心概念:

 

通知类都建在aop包中

核心概念为:

  • 连接点(JoinPoint):正在执行的方法,例如:update()、delete()、select()等都是连接点。

  • 切入点(Pointcut):进行功能增强了的方法,例如:update()、delete()方法,select()方法没有被增强所以不是切入点,但是是连接点。

    • 在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法

      • 一个具体方法:com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法

      • 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法

  • 通知(Advice):在切入点前后执行的操作,也就是增强的共性功能

    • 在SpringAOP中,功能最终以方法的形式呈现

  • 通知类:通知方法所在的类叫做通知类

  • 切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。

 

Aop的一些相关注解 

1.@EnableAspectJAutoProxy:开启注解格式AOP功能(写在springConfig中类上)
2.@Aspect:写在类上,标识该类为AOP的切面类(写在通知类上)
3.@Pointcut:在切面类中声明的一个私有方法上,用来定义切入点表达式
4.通知类型相关的注解,@Before,@After,@AfterReturning,@AfterThrowing,@Around

Aop的工作流程

  1. Spring容器启动

  2. 读取所有切面配置中的切入点

  3. 初始化bean,判定bean对应的类中的方法是否匹配到任意切入点

    • 匹配失败,创建原始对象

    • 匹配成功,创建原始对象(目标对象)的代理对象

  4. 获取bean执行方法

    • 获取的bean是原始对象时,调用方法并执行,完成操作

    • 获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

Aop的切入点表达试

切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)@Pointcut("execution(public User com.itheima.service.UserService.findById(int))")

但是我们在开发时 都会写成(@Pointcut("execution(* com.itheima.service.*Service.*(..))"))

表示: 有没有返回值都行 在com.itheima.service包下的以Service结尾的任意方法且方法内需要的参数有没有都行 满足上述要求的方法 都会进入通知类中进行方法内容的加强 (其中方法的定义根据具体需求来编写)

目的:可以使用通配符描述切入点,快速描述。

  • *:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

execution(public * com.itheima.*.UserService.find*(*))
  • .. :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法

execution(public User com..UserService.findById(..))
  • +:专用于匹配子类类型

execution(* *..*Service+.*(..))
 
 
Aop的通知分类
1前置通知 注解为 @Before     在切入点方法执行之前执行
2后置通知 注解为 @After     在切入点方法执行之后执行,无论切入点方法内部是否出现异常,后置通知都会执行。
3环绕通知 注解为 @Around (重点)  手动调用切入点方法并对其进行增强的通知方式。
                在通知类中的环绕通知方法上的返回值我们一般书写为Object
                    其中方法内的参数为ProceedingJoinPoint 类型  (ProceedingJoinPoint 的 对象这里 我就用 pjp 来代写了 方便书写)
                在环绕通知中 有几个重要的方法  pjp.proceed(); 其方法表示对原始方法进行了调用 其返回值为原始方法返回值 (例 我们在这里就可以 增强一些功能 在这个方法前后)
                pjp.getSignature(); 这个方法表示获取签名信息 就是可以通过这个方法来获取能够获取调用谁调用的这个通知的接口方法
                在这个getSignature()方法中的getgetDeclaringTypeName()就可以获得接口/类的全限定名
                getSignature()中的getName()方法可以获得其方法名 这两个方法就是可以让我们知道接口中那个方法来调用环绕通知进行增强的 方便我们进行增强
4 抛出异常后通知 @AfterThrowing 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行
5 返回后通知 @ AfterReturning 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法正常执行完毕后运行
 
案例一  :   测量业务层接口万次执行效率
通知类 代码如下图:

 

 案例二   :   百度网盘密码数据兼容处理(即输入密码时去掉可能会输入的空格)

 

 

 

Spring 事务管理(重点)

Spring事务的作用就是可以不止在数据层上事务保证一些方法的成功 spring 在业务层 也可以保障 (与之前事务的区别就在这里 之前的事务是只可以在数据层的)

spring 事务的注解 @Transactional (注如果是代理的话不要写在service类中接口中的方法上面),后来的话写在service包中的impl包中的实现类中方法上面

设置事务管理器 (设置在jdbc 中利用@Bean 来写)如下图 (注参数传入的dataSource 要与被的第三方管理的@Bean 是用一个)

 

 

要在springConfig中添加@EnableTransactionManagement注解 这样才能让事务开启

 

 spring 事务角色

分为

  • 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法

  • 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法

spring 事务回滚 有一些异常是回滚不了的 比如(编译时异常 (IOException是回滚不了的)),所以我们针对这种问题就要在@Transaction注解中添加一些配置(rollbackFor配置)来处理 如下图

 

 这样我们就可以来处理回滚不了的IOException异常

 

 spring 事务传播行为

spring事务 我们无法满足例如银行转账时回滚后异常 也想记录在日志中 我们就要在日志service接口中的@Transaction在进行配置让其留下记录

 

 利用propagation配置 

 

 

事务的传播行为解决的问题是:方法A调用方法B,两个方法如果均配置了事务,用来指定方法B的事务与方法A事务之间的关系。
1.PROPAGATION_REQUIRED: 如果方法A有事务,方法B就加入该事务,如果方法A无事务,方法B创建一个新事务
2.PROPAGATION_REQUIRES_NEW:不管方法A有没有事务,方法B都会新创建一个事务
3.PROPAGATION_SUPPORTS:如果方法A有事务,方法B就加入,如果方法A无事务,方法B也没有事务
4.PROPAGATION_NOT_SUPPORTED:不管方法A有没有事务,方法B都不会有事务
5.PROPAGATION_MANDATORY:如果方法A有事务,方法B加入该事务,如果方法A无事务,则直接报错
6.PROPAGATION_NEVER:如果方法A无事务,方法B也无事务,如果方法A有事务,则直接报错
propagation-required

其中的 1,2常用 1是默认的  propagation_REQUIRES_NEW 表示当你这个新事务有一些需求需要不跟这个事务管理员 满足要么成功要么失败的原子性 时就要用到这个配置 来独立门户

posted @ 2022-10-11 19:37  小垚java  阅读(75)  评论(0)    收藏  举报