前边章节已经介绍了声明通知,但如果想获取被被通知方法参数并传递给通知方法,该如何实现呢?接下来我们将介绍两种获取通知参数的方式。

  • 使用JoinPoint获取:Spring AOP提供使用org.aspectj.lang.JoinPoint类型获取连接点数据,任何通知方法的第一个参数都可以是JoinPoint(环绕通知是ProceedingJoinPoint,JoinPoint子类),当然第一个参数位置也可以是JoinPoint.StaticPart类型,这个只返回连接点的静态部分。

1) JoinPoint提供访问当前被通知方法的目标对象、代理对象、方法参数等数据:

package org.aspectj.lang;
import org.aspectj.lang.reflect.SourceLocation;
public interface JoinPoint {
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
Object getThis(); //返回AOP代理对象
Object getTarget(); //返回目标对象
Object[] getArgs(); //返回被通知方法参数列表
Signature getSignature(); //返回当前连接点签名
SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
String getKind(); //连接点类型
StaticPart getStaticPart(); //返回连接点静态部分
}

  2ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法:

public interface ProceedingJoinPoint extends JoinPoint {
public Object proceed() throws Throwable;
public Object proceed(Object[] args) throws Throwable;
}

  3) JoinPoint.StaticPart提供访问连接点的静态部分,如被通知方法签名、连接点类型等:

public interface StaticPart {
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}

  使用如下方式在通知方法上声明,必须是在第一个参数,然后使用jp.getArgs()就能获取到被通知方法参数:

@Before(value="execution(* sayBefore(*))")
public void before(JoinPoint jp) {} @Before(value="execution(* sayBefore(*))")
public void before(JoinPoint.StaticPart jp) {}

  

  • 自动获取:通过切入点表达式可以将相应的参数自动传递给通知方法,例如前边章节讲过的返回值和异常是如何传递给通知方法的。

在Spring AOP中,除了execution和bean指示符不能传递参数给通知方法,其他指示符都可以将匹配的相应参数或对象自动传递给通知方法。

@Before(value="execution(* test(*)) && args(param)", argNames="param")
public void before1(String param) {
System.out.println("===param:" + param);
}

  

切入点表达式execution(* test(*)) && args(param) :

1)首先execution(* test(*))匹配任何方法名为test,且有一个任何类型的参数;

2)args(param)将首先查找通知方法上同名的参数,并在方法执行时(运行时)匹配传入的参数是使用该同名参数类型,即java.lang.String;如果匹配将把该被通知参数传递给通知方法上同名参数。

其他指示符(除了execution和bean指示符)都可以使用这种方式进行参数绑定。

在此有一个问题,即前边提到的类似于【3.1.2构造器注入】中的参数名注入限制:class文件中没生成变量调试信息是获取不到方法参数名字的。

所以我们可以使用策略来确定参数名:

1、如果我们通过“argNames”属性指定了参数名,那么就是要我们指定的;

@Before(value=" args(param)", argNames="param") //明确指定了
public void before1(String param) {
System.out.println("===param:" + param);
}

  2、如果第一个参数类型是JoinPoint、ProceedingJoinPoint或JoinPoint.StaticPart类型,应该从“argNames”属性省略掉该参数名(可选,写上也对),这些类型对象会自动传入的,但必须作为第一个参数;

@Before(value=" args(param)", argNames="param") //明确指定了
public void before1(JoinPoint jp, String param) {
System.out.println("===param:" + param);
}

  3、如果“class文件中含有变量调试信息”将使用这些方法签名中的参数名来确定参数名;

@Before(value=" args(param)") //不需要argNames了
public void before1(JoinPoint jp, String param) {
System.out.println("===param:" + param);
}

  4、如果没有“class文件中含有变量调试信息”,将尝试自己的参数匹配算法,如果发现参数绑定有二义性将抛出AmbiguousBindingException异常;对于只有一个绑定变量的切入点表达式,而通知方法只接受一个参数,说明绑定参数是明确的,从而能配对成功。

@Before(value=" args(param)")
public void before1(JoinPoint jp, String param) {
System.out.println("===param:" + param);
}

  

5、以上策略失败将抛出IllegalArgumentException。

接下来让我们示例一下组合情况吧:

@Before(args(param) && target(bean) && @annotation(secure)",
argNames="jp,param,bean,secure")
public void before5(JoinPoint jp, String param,
IPointcutService pointcutService, Secure secure) {
……
}

  

图6-5 参数自动获取流程

除了上边介绍的普通方式,也可以对使用命名切入点自动获取参数:

@Pointcut(value="args(param)", argNames="param")
private void pointcut1(String param){}
@Pointcut(value="@annotation(secure)", argNames="secure")
private void pointcut2(Secure secure){} @Before(value = "pointcut1(param) && pointcut2(secure)",
argNames="param, secure")
public void before6(JoinPoint jp, String param, Secure secure) {
……
}

   自此给通知传递参数已经介绍完了,示例代码在cn.javass.spring.chapter6.ParameterTest文件中。

spring3: AOP 之 通知参数的更多相关文章

  1. spring3: AOP 之 通知顺序

    如果我们有多个通知想要在同一连接点执行,那执行顺序如何确定呢?Spring AOP使用AspectJ的优先级规则来确定通知执行顺序.总共有两种情况:同一切面中通知执行顺序.不同切面中的通知执行顺序. ...

  2. 开涛spring3(6.6) - AOP 之 6.6 通知参数

    前边章节已经介绍了声明通知,但如果想获取被被通知方法参数并传递给通知方法,该如何实现呢?接下来我们将介绍两种获取通知参数的方式. 使用JoinPoint获取:Spring AOP提供使用org.asp ...

  3. Spring AOP 四大通知

    Spring AOP 四大通知 Spring 3.X 以前 1.前置通知,实现  MethodBeforeAdvice 接口,重写 public  void  before(Method  metho ...

  4. AspectJ的拓展学习--织入顺序和通知参数指定

    前言: 其实spring的aop非常的强大, 因此研究一下AspectJ还是有必要, 而不是仅仅停留在初级的阶段. 比如spring的事务是基于aop来实现的, 如果不能深入的研究, 可能很多知识点, ...

  5. Spring笔记07(Spring AOP的通知advice和顾问advisor)

    1.Spring AOP的通知advice 01.接口代码: package cn.pb.dao; public interface UserDao { //主业务 String add(); //主 ...

  6. Spring AOP(通知、连接点、切点、切面)

    一.AOP术语 通知(Advice)  切面的工作被称为通知.通知定义了切面是什么以及何时使用.除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题.5种通知类型: 前置通知(Before): ...

  7. spring aop环绕通知

    [Spring实战]—— 9 AOP环绕通知   假如有这么一个场景,需要统计某个方法执行的时间,如何做呢? 典型的会想到在方法执行前记录时间,方法执行后再次记录,得出运行的时间. 如果采用Sprin ...

  8. Spring AOP前置通知实例说明AOP相关概念

    今天又看了下韩顺平的SpringAOP的讲解,讲解的很透彻.仿照视频自己使用下前置通知. 一.引出问题 有个接口TestServiceInter,有两个实现方法TestService和Test2Ser ...

  9. AOP 环绕通知 集成了前置 后置 返回通知等功能

    AOP 环绕通知 集成了前置 后置 返回通知等功能

随机推荐

  1. info 手册

      info flex 可以查看flex帮助. h就可以看到相关命令,常用命令已经加粗: x           关闭此帮助窗口. q           一并退出 Info. RET         ...

  2. 命名空间 <iostream>和<iostream.h> 由程序设计者命名的内存区域

    namespace_百度百科 https://baike.baidu.com/item/namespace/1700121?fromtitle=命名空间 namespace即“命名空间”,也称“名称空 ...

  3. 码云平台, Git提交需要输入用户名/密码, 怎么办

    这是因为, 检出代码的时候, 使用了http的方式: 那么, 改为ssh的地址就行了

  4. Redis资料汇总(转)

    原文:Redis资料汇总专题 很多朋友反映,说NoSQLFan上的资料不少,但是要找到自己实用的太难,于是萌生做这样一个专题的想法.通过将不同NoSQL产品从入门到精通的各种资料进行汇总,希望能够让大 ...

  5. Django - 文件上传、Django组件 - 分页器(paginator)

    一.文件上传准备知识 - Content-Type 1.请求头 - Content-Type Content-Type指的是请求体的编码类型,常见的类型共有3种: 1)application/x-ww ...

  6. Submission Details [leetcode] 算法的改进

    最先看到这一题,直觉的解法就是len从1到s1.size()-1,递归调用比較s1和s2长度为len的子串是否相等.以及剩余部分是否相等. 将s1分成s1[len + rest],分别比較s2[len ...

  7. 分布式计算hadoop三大组件

    设计原则:移动计算,而不是移动数据 计算层:Map/Reduce调度层:YARN数据层:HDFS 这三层之间没有必然的依赖性,只是经常这么搭配,而且都是hadoop那个包里一起安装的,三层都可以独立运 ...

  8. 购物单问题—WPS使用excel

    ****     180.90       88折 ****      10.25       65折 ****      56.14        9折 ****     104.65        ...

  9. C#简单实现动态数据生成Word文档并保存

    今天正好有人问我,怎么生成一个报表式的Word文档. 就是文字的样式和位置相对固定不变,只是里面的内容从数据中读取. 我觉得类似这种的一般用第三方报表来做比较简便.但既然要求了Word,只好硬着头皮来 ...

  10. 深入ff and ffbase

    用ff 包读取一个csv 文件 >options(fftempdir = [二进制文件存放的位置]) >file_chunks <- read.csv.ffdf(file=”big_ ...