背景:

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(三):切面的优先级、重复使用切入点表达式的更多相关文章

  1. spring-第十九篇AOP面向切面编程之增强处理的优先级

    1.从我们第十七篇举例了不同类型的增强处理. spring AOP采用和AspectJ一样的优先顺序来织入增强处理:在“进入”连接点时,具有最高优先级的增强处理将先被织入(在给定的两个Before增强 ...

  2. Spring之注解实现aop(面向切面编程)

    1:Aop(aspect object programming)面向切面编程,名词解释:    1.1:功能:让关注点代码与业务逻辑代码分离    1.2:关注点        重复代码就叫做关注点  ...

  3. [原创]java WEB学习笔记107:Spring学习---AOP切面的优先级,重用切点表达式

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. [原创]java WEB学习笔记105:Spring学习---AOP介绍,相关概念,使用AOP,利用 方法签名 编写 AspectJ 切入点表达式

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. 阶段3 2.Spring_08.面向切面编程 AOP_7 通用化切入点表达式

    下面配置了通用的表达式,,上面的四个就不用再配置那么长 索罗的切入点表达式了. 节省了每次都要写一长段表达式的过程 写在一个aop:aspect这个切面下面就只能当前切面用 写在切面里面 运行测试 挪 ...

  6. Spring Boot笔记九:AOP面向切面编程

    我参考的这篇文章,以验证身份为例讲解了什么是AOP AOP 这里只讲解一下怎么去实现AOP 新建一个类,叫HttpAspect用来切面 package com.vae.springboot.study ...

  7. spring学习九 spring aop详解

    本文来自于:https://www.cnblogs.com/jingzhishen/p/4980551.html AOP(Aspect-Oriented Programming,面向方面编程),可以说 ...

  8. Spring学习(十九)----- Spring的五种事务配置详解

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...

  9. 不依赖Spring使用AspectJ达到AOP面向切面编程

    网上大多数介绍AspectJ的文章都是和Spring容器混用的,但有时我们想自己写框架就需要抛开Spring造轮子,类似使用原生AspectJ达到面向切面编程.步骤很简单,只需要两步. 1.导入依赖 ...

随机推荐

  1. 给Eclipse安装eUML2插件以及可能出现的依赖错误解决方案(转)

    eUML2是一款强大的,基于Eclipse应用程序的UML建模工具.开发者可以在UML开发过程中将模型转化为Java代码:确保软件质量和减少开发时间. 必备条件 Java runtime 1.5 or ...

  2. STM32F4 Alternate function mapping

    #define GPIO_AF0_MCO // MCO (MCO1 and MCO2) Alternate Function mapping #define GPIO_AF0_RTC_50Hz // ...

  3. RednaxelaFX:软件工程师、主攻高级编程语言虚拟机的设计与实现

    https://www.zhihu.com/people/rednaxelafx/posts

  4. 在线即时展现 Html、JS、CSS 编辑工具 - JSFiddle

    在线即时展现 Html.JS.CSS 编辑工具 - JSFiddle 想对它做些说明介绍.但是它确是那么的easy使用. 兴许有时间,把左側列表作以相关介绍和演示样例演示吧.

  5. 在ASP.NET Web API中使用OData的单例模式

    从OData v4开始增加了对单例模式的支持,我们不用每次根据主键等来获取某个EDM,就像在C#中使用单例模式一样.实现方式大致需要两步: 1.在需要实现单例模式的导航属性上加上[Singleton] ...

  6. arcgis10.5.1 对齐要素

    许可级别:BasicStandardAdvanced 摘要 标识地理处理工具用于标识搜索距离中输入要素与目标要素的不一致部分并使其与目标要素一致. 插图 用法 警告: 此工具用于修改输入数据.有关详细 ...

  7. Winfrom固定Label宽度,根据文本动态改变Label的高度 z

    Label,要固定住宽度,然后根据文本的长度来动态改变高度,一开始去网上找解决方案,各种根据字体大小啊,字数啊来动态改变,但是效果却不怎么好.最后灵机一动,想起了偶尔用过一次的FlowLayoutPa ...

  8. Android基础笔记(九)- 广播

    广播的概念 广播的生命周期 案例-监听短信到来并解析短信内容 案例-拦截外拨电话并设置区号 案例-SD卡状态监听 介绍一些经常使用的广播 发送自己定义广播 有序广播和无序广播 启程!! ! 广播的概念 ...

  9. .NET:不要使用扩展方法扩展Object对象。

    C#的扩展方法算是一种Minin(掺入)机制,掺入方法有其合理的使用场景,这里说说一种不好的使用场景(个人意见):不要使用扩展方法扩展Object对象.扩展Object会对所有类型的示例有侵入,特别是 ...

  10. Convolutional Neural Networks at Constrained Time Cost(精读)

    一.文献名字和作者     Convolutional Neural Networks at Constrained Time Cost,CVPR 2015 二.阅读时间      2015年6月30 ...