Spring AOP之多切面运行顺序
多切面运行顺序
当一个方法的执行被多个切面共同切的时候,环绕通知只影响当前切面的通知顺序,例如创建两个切面logUtil,validateUtil两个切面共同监视计算器类的加法运算,add(int a,int b);测试中,看切面工具类的名称首字母,默认情况下a-z执行顺序,所以这个时候logUtil切面通知比validateUtil先执行通知;
所以顺序是:L的前置通知 -->v的前置通知–>执行add方法,然后v的后置通知–>V的后置返回–>L的后置通知–>L的后置返回。
但是当logUtil中加入了环绕通知,所以环绕通知要比logUtil的普通通知先执行,环绕通知功能很强大,在通过反射执行方法的前面我们可以更改这个方法的参数,但是普通通知不能这么做。虽然在logUtil加了环绕通知,但是这个环绕通知只是比logUtil的普通通知先执行无论是进入切面前还是出切面时,他并不影响validateUtil这个切面的普通通知的执行顺序,所以加了环绕通知执行顺序是
环绕前置–> log前置–>va前置–>目标方法–>va后置–>va返回–>环绕返回通知–>环绕后置–>log后置–>log返回。
图:
这里的validate切面就是图中的VaAspect;
对啦,可以更改默认的切面顺序,要在将要更改的切面类上加入@order(int value)注解,value默认值很大,超级大,越大执行的优先级越低,所以如果把它调成1就是先执行这个切面的通知。
AOP的应用场景:
aop可以进行日志记录;
aop可以做权限验证
AOP可以做安全检查
AOP可以做事务控制
回忆基于注解的AOC配置
将目标类和切面类都加入到IOC容器中。@Component
告诉Spring哪个是切面类@Aspect
在切面类中使用五个通知注解来配置切面中的这些方法都什么时候在那运行
开启注解的aop功能。
不使用注解实现AOP配置。
1.切面类
public class LogUtil {
public void performance(){}
public void logStart(JoinPoint joinPoint)
{
//获取方法上的参数列表
Object[] args = joinPoint.getArgs();
//获取方法签名
Signature signature = joinPoint.getSignature();
String name = signature.getName();//获取方法名
System.out.println("前置通知:"+name+" 方法开始执行了....参数是:"+ Arrays.asList(args) +"");
}
public void logReturn(JoinPoint point,Object result)
{
String name = point.getSignature().getName();
Object[] args = point.getArgs();
System.out.println("返回通知: "+name+"方法正常执行,返回结果是:"+result+"");
}
public void logException(JoinPoint point,Exception e)
{
String name = point.getSignature().getName();
System.out.println("异常通知:"+name+" 方法出现了异常,异常是 "+e+"...");
}
public void logEnd(JoinPoint joinPoint)
{
String name = joinPoint.getSignature().getName();
System.out.println("后置通知:"+name+"方法结束了");
}
//环绕通知
public Object myAround(ProceedingJoinPoint proceedingJoinPoint){
Object proceed = null;
//获取方法名
String name = proceedingJoinPoint.getSignature().getName();
//获取执行方法的参数列表
Object[] args = proceedingJoinPoint.getArgs();
try {
System.out.println("环绕前置通知:"+name+"方法开始执行了,参数是"+Arrays.asList(args)+"");
//等于 method.invoke();通过反射执行指定方法
proceed = proceedingJoinPoint.proceed();
System.out.println("环绕返回通知:"+name+"方法返回结果是"+proceed+";");
} catch (Throwable throwable) {
System.out.println("环绕异常通知:异常是"+throwable+"");
throwable.printStackTrace();
}finally {
System.out.println("环绕后置通知:"+name+"方法结束了");
}
return proceed;
}
2.被切入的类(这里是一个计算器类)
package main.java.cn.zixue.domain;public class MyCalculator
{
public int add(int a,int b)
{
return a+b;
}
public int sub(int a,int b)
{
return a-b;
}
public int mul(int a,int b)
{
return a*b;
}
public int dev(int a,int b)
{
return a/b;
}
public double add(double a,float b,int c)
{
return a+b+c;
}
}
3.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="main.java.cn"></context:component-scan>
<bean id="myCalculator" class="main.java.cn.zixue.domain.MyCalculator"></bean>
<bean id="logUtil" class="main.java.cn.zixue.utils.LogUtil"></bean>
<!--AOP名称空间-->
<aop:config>
<!-- 制定切面的方法-->
<aop:pointcut id="performance" expression="execution(public * main.java.cn.zixue.domain.MyCalculator.*(..))"></aop:pointcut>
<!--指定切面-->
<aop:aspect ref="logUtil">
<aop:after method="logEnd" pointcut-ref="performance"></aop:after>
<aop:before method="logStart" pointcut-ref="performance"></aop:before>
<aop:after-returning method="logReturn" pointcut-ref="performance" returning="result"></aop:after-returning>
<aop:after-throwing method="logException" pointcut-ref="performance" throwing="e"></aop:after-throwing>
<aop:around method="myAround" pointcut-ref="performance"></aop:around>
</aop:aspect>
</aop:config>
</beans>
4.测试结果
@Test
public void Test02()
{
MyCalculator myCalculator = (MyCalculator) context.getBean("myCalculator");
myCalculator.add(1,10);
System.out.println("========================");
}
前置通知:add 方法开始执行了…参数是:[1, 10]
环绕前置通知:add方法开始执行了,参数是[1, 10]
环绕返回通知:add方法返回结果是11;
环绕后置通知:add方法结束了
返回通知: add方法正常执行,返回结果是:11
后置通知:add方法结束了
====================**
普通前置通知->环绕通知->环绕返回->环绕后置->普通返回->普通后置
注解和配置文件在什么时候使用?该如何选择?
注解的优点:配置快速简洁。
配置文件的优点:功能丰富,注解有的他都可以实现,注解没有的他也有。
当遇到重要的切面时,用配置文件写,例如权限验证及管理。对于常用的普通的切面就用注解。
Spring AOP之多切面运行顺序的更多相关文章
- Spring AOP: 织入的顺序
spring AOP 采用和 AspectJ 一样的优先顺序来织入增强处理:在进入连接点时,高优先级的增强处理将先被织入:在退出连接点时,高优先级的增强处理会后被织入. 当不同的切面里的两个增强处理需 ...
- Spring AOP监控SQL运行
对数据库连接池Proxool比較熟悉的读者,都知道Proxool能够记录SQL运行内容和时间等信息日志. 我们能够将该日志记录专门的SQL日志文件.对于查找运行特别耗时的SQL起了不小的作用. 对于一 ...
- Spring AOP介绍与使用
Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 面向切面 ...
- Spring 4 官方文档学习(六)核心技术之Spring AOP
目录 1.介绍 1.1.AOP概念 1.2.Spring AOP 能力 和 目标 1.2.1.简介 1.2.2.@AspectJ 支持 1.2.3.声明一个aspect 例子 1.2.4.声明advi ...
- Spring AOP概念及作用
一:SpringAOP概念 面向切面编程(Aspect Oriented Programming)提高了另一种角度来思考程序的结构,通过预编译方式和运行期间的动态代理实现程序功能的统一维护的一种技术. ...
- Spring AOP 扫盲
关于AOP 面向切面编程(Aspect-oriented Programming,俗称AOP)提供了一种面向对象编程(Object-oriented Programming,俗称OOP)的补充,面向对 ...
- Spring Aop 详解一
Aop 是一个编程思想,最初是一个理论,最后落地成了很多的技术实现. 我们写一个系统,都希望尽量少写点儿重复的东西.而很多时候呢,又不得不写一些重复的东西.比如访问某些方法的权限,执行某些方法性能的日 ...
- 运用Spring Aop,一个注解实现日志记录
运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...
- Spring AOP 实现原理与 CGLIB 应用
https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/ AOP(Aspect Orient Programming),也就是面向 ...
随机推荐
- AcWing 337. 扑克牌
大型补档计划 题目链接 把状态实质相同的划分为一类... 发现花色.具体牌值的多少均不影响方案,考虑等效转化题目. 设 \(f[A][B][C][D][k]\) A 个 1 张相同,B 个 2 张相同 ...
- Acwing 393. 雇佣收银员
算法1: 差分约束 + 枚举 O(Tn2028) 由于牵扯到 \([i - 8 + 1, i]\) 这段区间的和的约束,所以用前缀和更好表达一些. 设 \(num[i]\)表示 \(i\) 时刻有多少 ...
- SP7022 CPATTERN - Cow Patterns
本篇题解用于作者本人加深理解,也欢迎大家阅读. 这道题的正解是\(KMP\)加上树状数组,记录每一个位置前几个位置比其小的.相等的.大的数的数量,比较方式便是比较相应的数量,若相等,则匹配成功. 但是 ...
- PCRE正则表达式语法
字符 描述 \ 将下一个字符标记为一个特殊字符,或一个原义字符,或一个向后引用,或一个八进制转义符.例如,"\n"匹配一个换行符. ^ 匹配输入字符串的开始位置. $ 匹配输入字符 ...
- ES6新增api随记
求一个数组中的最大值 Math.max.apply(null,[1,2,3,4])=>Math.max(...[1,2,3]) 讲一个数组中的元素全部添加到另一个数组中 let arr=[1,2 ...
- MySQL02-约束
1.DQL查询语句 1.1 排序查询 语法:order by 排序字段1 排序方式1 , 排序字段2 排序方式2... 排序方式: ASC:升序,默认的. DESC:降序. 注意: 如果有多个排序条 ...
- 多任务-python实现-进程(2.1.7)
@ 目录 1.进程是什么 2.进程的生命周期 3.Python中多进程的实现 4.进程和线程的区别 1.进程是什么 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源 ...
- SpringBoot从入门到精通教程(一)
写在前面的话: 在很早之前,记笔记时候,我就一直在思考一个问题,我记笔记是为了什么,我一直想不明白 ,后面发现技术跟新迭代的速度实在太快了,笔记刚纪完,技术又跟新了,于是我想了想干脆边写博客,边记笔记 ...
- 使用h5开发跨平台APP确保数据安全交互---服务器篇
从eclipse到android studio的安卓开发经验告诉我原声开发才是硬道理,其实以前很抵触html5开发app的,虽然没有去了解过,但是冥冥中就觉得它运行速度太慢了,加载渲染根本比不上原生开 ...
- sql 查询条件为拼接字符串 不能使用IN 使用patindex查询结果集
题目: 求组织机构ID在('5dc8de20-9f2f-465e-afcc-f69abecaee50','63549b63-1e0d-4269-98f4-013869d7f211','f7316bf3 ...