前边已经学习了声明通知,但如果想获取被被通知方法参数并传递给通知方法,该如何实现呢?接下来我们将介绍两种获取通知参数的方式。
一、使用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(); //返回连接点静态部分 }
2)ProceedingJoinPoint:用于环绕通知,使用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) { …… }
该示例的执行步骤如图所示:
除了上边介绍的普通方式,也可以对使用命名切入点自动获取参数:
@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/
相关推荐
通知参数(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 Boot结合AOP可以方便地实现日志的统一处理,通过定义切点和通知,我们可以灵活地控制日志记录的时机和内容,从而提高代码的可维护性和可读性。在实际项目中,根据需求,我们可以进一步定制日志格式...
标题 "Spring AOP.rar" 涉及到的是Spring框架中的一个重要特性——面向切面编程(Aspect Oriented Programming,简称AOP)。AOP是Spring框架提供的一种强大的功能,它允许我们在不修改源代码的情况下,对应用程序...
- **AOP概念和实现**:讲解AOP的基本概念,如切面、通知、目标对象等,以及如何在Spring中实现AOP。 - **数据访问**:涵盖了JDBC模板、ORM集成、事务管理等内容,帮助开发者高效地处理数据库操作。 - **Web MVC**...
在Spring AOP(面向切面编程)中实现日志分析管理是一种常见的做法,它能帮助开发者跟踪和理解系统运行过程中的行为,同时提供详细的错误日志以支持运维工作。通过元注解的方式,我们可以轻松地将日志记录功能集成到...
3. 在Spring的配置文件中,使用<aop:config>元素声明切面,使用<aop:advisor>元素定义通知。例如,创建一个名为myAspect的切面,定义一个切入点表达式,并添加前置通知: ```xml <aop:config> <aop:aspect id=...
在Spring框架中,AOP(Aspect Oriented Programming,面向切面编程)是一种强大的设计模式,它允许程序员在不修改源代码的情况下,通过插入被称为“切面”的代码来增强功能或处理横切关注点,如日志、事务管理、权限...
在Spring MVC框架中,AOP(面向切面编程)是一种强大的工具,允许我们在不修改源代码的情况下,插入横切关注点,例如日志记录、事务管理等。本篇将深入探讨如何利用AOP和自定义注解来实现日志记录功能。 首先,我们...
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e" /> <aop:after method="myAfter" pointcut-ref="myPointCut" /> </aop:aspect> </aop:config> ``` 在上述示例中: - `...
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进行依赖注入 ...
6. **@Before、@After、@AfterReturning、@AfterThrowing**:除了`@Around`,Spring AOP还提供了其他四种通知类型:`@Before`(前置通知,在目标方法之前执行)、`@After`(最终通知,在目标方法之后执行,无论是否...
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 ...
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. 声明一个...
- **传统AOP**:通过`<aop:config>`标签配置切点和通知,可以使用`<aop:advisor>`结合`<aop:pointcut>`或直接在`<aop:advisor>`中指定切点表达式。 - **AspectJ AOP**:使用注解的方式更简洁,例如`@Component`、`...
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. 声明一个切入点...
对于需要代理非接口类或者需要更复杂的织入逻辑的情况,开发者可能需要转向如 Spring AOP 或 AspectJ 这样的第三方框架。这些框架提供了更强大的AOP支持,包括类型级别的织入、切面定义、通知类型等,可以更好地适应...
2. **上下文配置命名空间**: 改进了上下文配置命名空间,例如 `<aop:spring-configured>` 移动到 `<context:spring-configured>`。 3. **基于注解的配置**: 引入了基于注解的配置支持,如 `@Component` 和 `@...
切点是在应用程序中定义的一组特定方法,当这些方法被执行时,AOP(面向切面编程)的通知(Advices)将被触发。@Pointcut注解允许开发者声明这些切点表达式,使AspectJ能够根据这些表达式识别方法,并在适当的时候应用...
7. **StatefulRetryOperationsInterceptor**: 这是一个基于Spring AOP的拦截器,可以用于方法级别的重试。它会存储每个重试的状态,以便在后续的重试中恢复到正确的位置。 以下是一个使用Spring Retry的例子: ```...