SpringAOP
前言
- 我的这篇AOP博客有大量的图片和例子教会怎么使用AOP
- 配置那里如果没有学习Maven的话也别急 就是使用maven下载了jar包而已了 你完全可以自己手动导入
- 如果你有一些代码比如说 事务 或者 日志等操作 需要大量嵌入你的代码前后的话 那么无疑AOP是最好用的
- AOP运行流程 : 首先调用前置通知(你可以认为最一开始初始的东西)->你的逻辑代码(这里先不说环绕通知)->你的代码有两种情况有可能正常返回, 有可能抛出异常
- 正常返回调用返回通知
- 抛出异常调用异常通知
- 最后一定会调用后置通知(你可以当做是try-catch的finally里的代码这里执行顺序里面有点问题 到时候可以看注意事项)
- 这里就是给你大致的一个了解没看懂也没事
文章目录
AOP实现方式
AOP几个相关概念
切面
- 就相当于一个代码插入到一个环境里 常用的方法是使用模版方法模式实现
- 或者使用**@Aspect**注解
连接点
建议/通知
- 某个切面在特定的连接点加一些东西. 许多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
在被代理对象的方法抛出异常后调用
异常通知,要求运行过程中产生异常