背景:

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. 在fork的项目里同步别人新增分支的方法

    # 1.将项目B clone 到本地 git clone -b master 项目B的git地址 # 2.将项目A的git地址,添加至本地的remote git remote add upstream ...

  2. 你的产品适不适合做微信小程序?你需要这篇产品逻辑分析

      自2017年1月9日张小龙宣布万众瞩目的“微信小程序”正式上线了.以名字看,感觉像是突出了“将你的程序接入微信”的意思. 我们此前分析过微信的功能迭代节奏:一般微信重要的功能规划周期,大约会在在9 ...

  3. 在.net core 2.0中生成exe文件

    .net core 2.0程序默认生成的是一个dll,需要通过dotnet命令来执行他. dotnet ConsoleApp1.dll 这种方式有点类似于java程序.本身这种方式没有什么问题,但在调 ...

  4. [Go] Cookie 使用简介

    Golang 的 Cookie web 开发免不了要和 cookie 打交道.Go 的 http 库也提供了 cookie 的相关操作. type Cookie struct { Name strin ...

  5. Win10正式版开机慢怎么办 开机黑屏时间长怎么办

    升级Win10正式版后开机速度慢.黑屏时间长怎么解决呢?其实我重要是由Win10正式版所提供的“快速启动”功能与电脑显卡驱动.电源管理驱动不兼容所造成的.下面就与大家分享一下针对Win10正式版开机速 ...

  6. 在ASP.NET MVC中使用Boostrap实现产品的展示、查询、排序、分页

    在产品展示中,通常涉及产品的展示方式.查询.排序.分页,本篇就在ASP.NET MVC下,使用Boostrap来实现. 源码放在了GitHub: https://github.com/darrenji ...

  7. Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out

    问题: java连接不上redis. 异常信息: Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.ne ...

  8. xheditor-文件上传-java-支持html5-application/octet-stream

    package reyo.sdk.utils.file; import java.io.BufferedOutputStream; import java.io.File; import java.i ...

  9. SharePoint Online 创建和使用视图

    前言 本文介绍如何在Office 365中创建和使用视图. 正文 首先,解释一下什么是SharePoint站点视图,所谓视图,就是列表的一个呈现形式,包含特定的栏.排序.筛选.分组等特性,我们通常创建 ...

  10. 用 iOS-System-Services 框架获取iOS设备所用的设备信息

    参考资料地址 https://github.com/Shmoopi/iOS-System-Services 百度云盘下载地址 http://pan.baidu.com/s/1c05ot1m This ...