Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式
背景:
1)指定切面优先级示例:有的时候需要对一个方法指定多个切面,而这多个切面有时又需要按照不同顺序执行,因此,切面执行优先级别指定功能就变得很实用。
2)重复使用切入点表达式:上一篇文章中,定义前置、后置、返回、异常通知的切入点表达式时,都使用了同一个;而且本章节新加入的验证切面ValidateAspect类,也使用同一个切入点表达式,怎么让他们重用呢?
指定切面优先级示例:
比如在算术计算器执行计算之前进行数据验证,验证完事之后才让执行日志输出。
新建spring aop项目参考:《Spring(十八):Spring AOP(二):通知(前置、后置、返回、异常、环绕)》
添加验证切面类:
package com.dx.spring.beans.aop; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; @Component
@Aspect
public class ValidateAspect {
@Before("execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(..))")
public void beforeMethod() {
System.out.println("validate...");
}
}
除了验证切面,还包含日志切面:
package com.dx.spring.beans.aop; import java.util.List;
import java.util.Arrays; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; //把这个类声明为一个切面:需要把该类放入到IOC容器中、再声明为一个切面。
@Aspect
@Component
public class LoggingAspect {
// 声明该方法为一个前置通知:在目标方法开始之前执行
@Before("execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(int, int))")
public void beforeMethod(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println("before method " + methodName + " with " + args);
} // 声明该方法为一个后置通知:在目标方法结束之后执行(无论方法是否抛出异常)。
// 但是因为当方法抛出异常时,不能返回值为null,因此这里无法获取到异常值。
@After(value = "execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(int,int))")
public void afterMethod(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println("after method " + methodName);
} /**
* 声明该方法为一个返回通知:在目标方法返回结果时后执行(当方法抛出异常时,无法执行)。 但是因为当方法抛出异常时,类似代码 {@code
* try <br/>
* { <br/>
* // before 前置通知 <br/>
* // do action method <br/>
* // after returning 返回通知,可以访问到方法的返回值 <br/>
* } catch(Exception e){ e.printStackTrace(); // after throwing
* 异常通知,可以访问到方法出现的异常 } // after 后置通知,因为方法可以抛出异常,所以访问不到方法的返回值 }
*/
@AfterReturning(value = "execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(int,int))", returning = "result")
public void afterReturningMethod(JoinPoint joinpoint, Object result) {
String methodName = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println(
"after method " + methodName + " with returning " + (result == null ? "NULL" : result.toString()));
} /**
* 定义一个异常通知函数: 只有在方法跑吹异常时,该方法才会执行,而且可以接受异常对象。
*/
@AfterThrowing(value = "execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(int,int))", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinpoint, Exception ex) {
String methodName = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println(
"after method " + methodName + " occurs exception: " + (ex == null ? "NULL" : ex.getMessage()));
} // @Around(value = "execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(int, int))")
// public Object aroundMethod(ProceedingJoinPoint pJoinPoint) throws Exception {
// String methodName = pJoinPoint.getSignature().getName();
// List<Object> args = Arrays.asList(pJoinPoint.getArgs());
//
// Object result = null;
// try {
// // 前置通知
// System.out.println("before method " + methodName + " with " + args);
// // 执行目标方法
// result = pJoinPoint.proceed();
// // 返回通知
// System.out.println("after method " + methodName + " returning " + result);
// } catch (Throwable ex) {
// // 异常通知
// System.out.println("after method " + methodName + " occurs exception: " + ex.getMessage());
// throw new Exception(ex);
// }
// // 后置通知
// System.out.println("after method " + methodName);
// return result;
// }
}
默认打印结果:

按照实际业务需求来讲,更希望是先执行验证切面,才执行日志切面,那么,可以通过设置切面优先级别来设置:
修改ValidateAspect.java添加注解@Order(1)
@Order(value=1)
@Component
@Aspect
public class ValidateAspect {
@Before("execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(..))")
public void beforeMethod() {
System.out.println("validate...");
}
}
修改LoggingAspect.java添加注解@Order(2)
@Order(value=2)
@Aspect
@Component
public class LoggingAspect {
//代码
}
此时执行结果为:

重使用切入点表达式:
上一篇文章中,定义前置、后置、返回、异常通知的切入点表达式时,都使用了同一个;而且本章节新加入的验证切面ValidateAspect类,也使用同一个切入点表达式,怎么让他们重用呢?
第一步:修改LoggingAspect切面类,添加@Pointcut注解的方法declareAspectJoinPointExpression():
//把这个类声明为一个切面:需要把该类放入到IOC容器中、再声明为一个切面。
@Order(value=2)
@Aspect
@Component
public class LoggingAspect {
@Pointcut("execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(..))")
public void declareAspectJoinPointExpression(){ }
//...
}
第二步:修改LoggingAspect切面类,把前置、后置、返回、异常、环绕通知方法的切入点表达式替换为“declareAspectJoinPointExpression()”
以前置通知方法为例:
//把这个类声明为一个切面:需要把该类放入到IOC容器中、再声明为一个切面。
@Order(value=2)
@Aspect
@Component
public class LoggingAspect {
@Pointcut("execution(public int com.dx.spring.beans.aop.IArithmeticCalculator.*(..))")
public void declareAspectJoinPointExpression(){ }
// 声明该方法为一个前置通知:在目标方法开始之前执行
@Before("declareAspectJoinPointExpression()")
public void beforeMethod(JoinPoint joinpoint) {
String methodName = joinpoint.getSignature().getName();
List<Object> args = Arrays.asList(joinpoint.getArgs());
System.out.println("before method " + methodName + " with " + args);
}
//...
}
第三步:修改验证切面类ValidateAspect.java:
@Order(value=1)
@Component
@Aspect
public class ValidateAspect {
@Before("com.dx.spring.beans.aop.LoggingAspect.declareAspectJoinPointExpression()")
public void beforeMethod() {
System.out.println("validate...");
}
}
备注:如果在同一个包下,可以不指定包的路径。
第四步:验证

Spring(十九):Spring AOP(三):切面的优先级、重复使用切入点表达式的更多相关文章
- spring-第十九篇AOP面向切面编程之增强处理的优先级
1.从我们第十七篇举例了不同类型的增强处理. spring AOP采用和AspectJ一样的优先顺序来织入增强处理:在“进入”连接点时,具有最高优先级的增强处理将先被织入(在给定的两个Before增强 ...
- Spring之注解实现aop(面向切面编程)
1:Aop(aspect object programming)面向切面编程,名词解释: 1.1:功能:让关注点代码与业务逻辑代码分离 1.2:关注点 重复代码就叫做关注点 ...
- [原创]java WEB学习笔记107:Spring学习---AOP切面的优先级,重用切点表达式
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 阶段3 2.Spring_08.面向切面编程 AOP_7 通用化切入点表达式
下面配置了通用的表达式,,上面的四个就不用再配置那么长 索罗的切入点表达式了. 节省了每次都要写一长段表达式的过程 写在一个aop:aspect这个切面下面就只能当前切面用 写在切面里面 运行测试 挪 ...
- Spring Boot笔记九:AOP面向切面编程
我参考的这篇文章,以验证身份为例讲解了什么是AOP AOP 这里只讲解一下怎么去实现AOP 新建一个类,叫HttpAspect用来切面 package com.vae.springboot.study ...
- spring学习九 spring aop详解
本文来自于:https://www.cnblogs.com/jingzhishen/p/4980551.html AOP(Aspect-Oriented Programming,面向方面编程),可以说 ...
- Spring学习(十九)----- Spring的五种事务配置详解
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...
- 不依赖Spring使用AspectJ达到AOP面向切面编程
网上大多数介绍AspectJ的文章都是和Spring容器混用的,但有时我们想自己写框架就需要抛开Spring造轮子,类似使用原生AspectJ达到面向切面编程.步骤很简单,只需要两步. 1.导入依赖 ...
随机推荐
- http://www.liangxiansen.cn/2017/04/06/consul/
Consul 使用手册 | 一个梦 http://www.liangxiansen.cn/2017/04/06/consul/ 基于Consul的分布式锁实现 https://mp.weixin.qq ...
- HTML5中的跨文档消息传递
跨文档消息传送(cross-document messaging),有时候也简称为XDM,指的是来自不同域的页面间传递消息.例如,www.w3cmm.com域中的一个页面与一个位于内嵌框架中的p2p. ...
- HDU 4123 Bob’s Race(树形DP,rmq)
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- LINUX IO 图解
http://blog.chinaunix.net/uid/29075379/cid-183430-list-1.html
- WCF技术我们应该如何以正确的方式去学习掌握
一.WCF技术我该如何学习? 阿笨的回答是:作为初学者的我们,那么请跟着阿笨一起玩WCF吧,阿笨将带领大家如何以正确的姿势去掌握WCF技术.由于WCF技术知识点太多了,就纯基础概念性知识都可以单独出一 ...
- 报错:Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
在保存数据的时候报这个错误,知道是验证错误,但到底是哪个属性验证错误呢? →打断点,运行,观察程序出错的地方→在出错的部分添加try...catch语句块→添加监视,输入((System.Data.E ...
- iOS sqlite 使用事务操作数据库
业务层代码: //将解析的更新人员数据批量同步到数据库 +(void)operateCompUsers:(NSMutableArray*)operateCompUsers { sqliteHelper ...
- HTML5之SVG
1.背景 SVG是Scalable Vector Graphics的缩写,意为可缩放矢量图形.1998年,万维网联盟成立了一个工作组,研发一种通过 XML来表现矢量图形的技术——SVG!由于SVG也是 ...
- 【SVN】如果windows用户忘记了svn的用户名和密码怎么办?
如果windows用户忘记了svn的用户名和密码怎么办? 1>你得进入默认地址 C:\Users\Administrator\AppData\Roaming\Subversion\auth\sv ...
- .NET:分布式事务
背景 分布式事务使用起来比较方便,不过也是有成本的,因此如果可以不用就尽量不用,比如:采用saga.如果采用了分布式事务的话,就需要对分布式事务相关的几个概念有所了解. 分布式事务 相关角色: 事务发 ...