SpringAOP超详细教学
阅读原文时间:2021年04月20日阅读:1

SpringAOP


前言

  • 我的这篇AOP博客有大量的图片和例子教会怎么使用AOP
  • 配置那里如果没有学习Maven的话也别急 就是使用maven下载了jar包而已了 你完全可以自己手动导入
  • 如果你有一些代码比如说 事务 或者 日志等操作 需要大量嵌入你的代码前后的话 那么无疑AOP是最好用的
  • AOP运行流程 : 首先调用前置通知(你可以认为最一开始初始的东西)->你的逻辑代码(这里先不说环绕通知)->你的代码有两种情况有可能正常返回, 有可能抛出异常
  • 正常返回调用返回通知
  • 抛出异常调用异常通知
  • 最后一定会调用后置通知(你可以当做是try-catch的finally里的代码这里执行顺序里面有点问题 到时候可以看注意事项)
  • 这里就是给你大致的一个了解没看懂也没事

文章目录

AOP实现方式

AOP几个相关概念



切面

  • 就相当于一个代码插入到一个环境里 常用的方法是使用模版方法模式实现
  • 或者使用**@Aspect**注解

连接点

  • 在Spring里体现为方法

建议/通知

  • 某个切面在特定的连接点加一些东西. 许多AOP框架(包括Spring) 将建议建模为拦截器.
  • 在连接点周围维护一系列拦截器

切入点(核心)

  • 匹配连接点的谓词,
  • Spring默认使用AspectJ切入点表达式语言

织入

  • 把特有的代码逻辑织入原有的代码逻辑

建议类型

  • 建议之前(前置通知):例如:在方法(连接点)之前可以检查代码逻辑的正确性
  • 放回建议后(方法正常完成后执行的建议):方法返回不抛出异常
  • 抛出建议后:抛出异常执行的方法
  • 在(最终建议之后):无论连接点退出的方式正确与否,都会执行的建议.
  • 围绕建议:这是最强大的通知,可以直接改变原有代码的逻辑性

注意事项(重要)

  • 首先XML和注解的方式的几个通知的顺序不太一样
  • XML:Before->Around反射前的代码->Around反射后的代码->After->AfterReturning(AfterThrowing)
  • 注解的是:Around反射前的代码->Before->Around反射后的代码->AfterReturning(AfterThrowing)->After
  • 下面XML版本的类名有两个好像忘记加Advice了 如果用他使用注解就重名了 会出错
  • 读者使用的时候自行加上

例子及知识点


XML版本

配置工作

在pom.xml引入依赖
maven这里只是引入jar包

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.9.1</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.1</version>
</dependency>

例子:入门例子前置通知

两个类
通知的类

模拟需要的服务类

然后再Spring配置文件中写入

但是可能无法生效

得在Spring容器中配置这个bean通过 容器getBean获得


下面的这个id如果需要被外部引用则配置

  • 上面的表达式的格式 第一个是权限修饰符(可以省略 可以写星号)
  • **第二个是返回类型 **
  • 第三个是哪个类下的哪个方法 也可以写*号
  • 参数(…) 表示任意参数, 也可以没有参数, 无数个参数也可以
  • 并且对于execution的参数是严格类型的比如
  • 无法对String和Integer类型的参数织入

  • 修改类添加一个before方法 传入参数org.aspectj.lang.JoinPoint

    然后织入

    这两个before方法都会执行 谁在上面谁先执行
    org.aspectj.lang.JoinPoint这个参数会获得切入点的信息 刚才可以获取方法名 还可以获取参数等等…
    例如可以通过上述的功能记录日志 通过org.aspectj.lang.JoinPoint获得方法名 参数 等等一系列

例子:通过返回通知获取结果


修改service类

返回通知类 这里的入参可以通过配置文件获得这个结果值

配置到配置文件中

同样的aop配置文件 织入连接点

测试函数

结果

例子:异常通知

后面有些和上面的一样的就不啰嗦了 看图


结果如下图

例子:环绕通知





结果如下图

居然只是打印了环绕通知…
这里根本就没有放行也就说他掌握着你连接点的生杀大权

例子:带处理过程入参的环绕通知


然后结果如下


注解版本

  • 因为之前的XML版本基础已经OK了 后面我会使用全部注解的版本
  • 下图是使用注解的两个容器类


  • 需要扫描advice下的通知类
  • 然后业务类很简单的一个模拟

  • 上面的@Pointcut注解相当于定义一个模版 后面可以不用重复写切入点
  • 例如下面的后置通知
  • 只需要引入那个类的方法名即可
  • 等价于@After(“execution(public * com.theSevenSky.service.StudentService.*(…))”)
  • 剩下几个同理



  • (注):值得注意的是返回通知如果带入参但是没有返回值 这个方法是不生效的
  • (注):所以我上述的例子需要删除入参 如下图

    测试类如下图

    结果如下

多个切面问题

画一张图应该就很好理解
这个图是来源Java EE SSM那本书上的

总结AOP的几种通知

注解/XML属性

通知

备注

@Before/aop:before

在被代理对象的方法前先调用

前置通知

@Around/aop:around

将被代理对象的方法封装起来,用环绕通知取代他

环绕通知,可以通过反射使用原有方法

@After/aop:after

在被代理对象的方法后调用

后置通知

@AfterReturning/aop:after-returning

在被代理对象的方法正常返回后调用

返回通知,要求运行过程中没有产生异常

@AfterThrowing/aop:after-throwing

在被代理对象的方法抛出异常后调用

异常通知,要求运行过程中产生异常