`

05-Spring3 AOP E_通知参数

阅读更多

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

一、使用JoinPoint获取

Spring AOP提供使用org.aspectj.lang.JoinPoint类型获取连接点数据,任何通知方法的第一个参数都可以是JoinPoint(环绕通知是ProceedingJoinPointJoinPoint子类),当然第一个参数位置也可以是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中,除了executionbean指示符不能传递参数给通知方法,其他指示符都可以将匹配的相应参数或对象自动传递给通知方法。

@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,且有一个任何类型的参数;

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

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

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

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

 

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

 

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

 

2、如果第一个参数类型是JoinPointProceedingJoinPointJoinPoint.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) {
……
}

 

该示例的执行步骤如图所示:

 

 

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

	
@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) {
……
}

  

 转自http://jinnianshilongnian.iteye.com/

 

 

  • 大小: 47.4 KB
分享到:
评论

相关推荐

    Spring-Reference_zh_CN(Spring中文参考手册)

    通知参数(Advice parameters) 6.2.4.7. 通知(Advice)顺序 6.2.5. 引入(Introductions) 6.2.6. 切面实例化模型 6.2.7. 例子 6.3. Schema-based AOP support 6.3.1. 声明一个切面 6.3.2. 声明一个切入点 6.3.3....

    spring aop的注解配置中,前置,后置,环绕通知,以及异常通知怎么获得被代理方法的参数

    在Spring AOP(面向切面编程)中,我们可以通过注解配置来实现对目标方法的增强,例如前置通知、后置通知、环绕通知和异常通知。这些通知在特定的时机执行,提供了灵活的代码逻辑插入点。下面我们将详细探讨如何在...

    spring boot aop 统一处理日志

    总结来说,Spring Boot结合AOP可以方便地实现日志的统一处理,通过定义切点和通知,我们可以灵活地控制日志记录的时机和内容,从而提高代码的可维护性和可读性。在实际项目中,根据需求,我们可以进一步定制日志格式...

    Spring aop.rar

    标题 "Spring AOP.rar" 涉及到的是Spring框架中的一个重要特性——面向切面编程(Aspect Oriented Programming,简称AOP)。AOP是Spring框架提供的一种强大的功能,它允许我们在不修改源代码的情况下,对应用程序...

    Spring2.5-中文参考手册 chm格式

    - **AOP概念和实现**:讲解AOP的基本概念,如切面、通知、目标对象等,以及如何在Spring中实现AOP。 - **数据访问**:涵盖了JDBC模板、ORM集成、事务管理等内容,帮助开发者高效地处理数据库操作。 - **Web MVC**...

    spring aop实现日志分析管理

    在Spring AOP(面向切面编程)中实现日志分析管理是一种常见的做法,它能帮助开发者跟踪和理解系统运行过程中的行为,同时提供详细的错误日志以支持运维工作。通过元注解的方式,我们可以轻松地将日志记录功能集成到...

    spring aop两种配置方式

    3. 在Spring的配置文件中,使用<aop:config>元素声明切面,使用<aop:advisor>元素定义通知。例如,创建一个名为myAspect的切面,定义一个切入点表达式,并添加前置通知: ```xml <aop:config> <aop:aspect id=...

    SpringAOP禁止非法请求路径实例

    在Spring框架中,AOP(Aspect Oriented Programming,面向切面编程)是一种强大的设计模式,它允许程序员在不修改源代码的情况下,通过插入被称为“切面”的代码来增强功能或处理横切关注点,如日志、事务管理、权限...

    SpringMVC利用AOP实现自定义注解记录日志

    在Spring MVC框架中,AOP(面向切面编程)是一种强大的工具,允许我们在不修改源代码的情况下,插入横切关注点,例如日志记录、事务管理等。本篇将深入探讨如何利用AOP和自定义注解来实现日志记录功能。 首先,我们...

    基于java的企业级应用开发:AspectJ开发.ppt

    <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e" /> <aop:after method="myAfter" pointcut-ref="myPointCut" /> </aop:aspect> </aop:config> ``` 在上述示例中: - `...

    spring chm文档

    6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.7. 编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 ...

    spring boot如何使用spring AOP实现拦截器

    6. **@Before、@After、@AfterReturning、@AfterThrowing**:除了`@Around`,Spring AOP还提供了其他四种通知类型:`@Before`(前置通知,在目标方法之前执行)、`@After`(最终通知,在目标方法之后执行,无论是否...

    Spring中文帮助文档

    6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.6.1. 理解AOP代理 6.7. 以编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ进行domain ...

    Spring 2.0 开发参考手册

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个...

    java事务管理&ssh整合笔记

    - **传统AOP**:通过`<aop:config>`标签配置切点和通知,可以使用`<aop:advisor>`结合`<aop:pointcut>`或直接在`<aop:advisor>`中指定切点表达式。 - **AspectJ AOP**:使用注解的方式更简洁,例如`@Component`、`...

    Spring API

    6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点...

    java-用Java动态代理实现AOP.pdf

    对于需要代理非接口类或者需要更复杂的织入逻辑的情况,开发者可能需要转向如 Spring AOP 或 AspectJ 这样的第三方框架。这些框架提供了更强大的AOP支持,包括类型级别的织入、切面定义、通知类型等,可以更好地适应...

    《Spring In Action》

    2. **上下文配置命名空间**: 改进了上下文配置命名空间,例如 `<aop:spring-configured>` 移动到 `<context:spring-configured>`。 3. **基于注解的配置**: 引入了基于注解的配置支持,如 `@Component` 和 `@...

    如何使用Spring Boot的@Pointcut注解

    切点是在应用程序中定义的一组特定方法,当这些方法被执行时,AOP(面向切面编程)的通知(Advices)将被触发。@Pointcut注解允许开发者声明这些切点表达式,使AspectJ能够根据这些表达式识别方法,并在适当的时候应用...

    spring-retry:使用spring-retry项目的例子

    7. **StatefulRetryOperationsInterceptor**: 这是一个基于Spring AOP的拦截器,可以用于方法级别的重试。它会存储每个重试的状态,以便在后续的重试中恢复到正确的位置。 以下是一个使用Spring Retry的例子: ```...

Global site tag (gtag.js) - Google Analytics