当前位置: 首页 > 知识库问答 >
问题:

AspectJ:基于参数值的拦截方法

拓拔霄
2023-03-14

我正在使用AeyJ拦截一个名为Request(String, String)的方法。为此,我使用了我自己指定的(标记)注释。这就是类的样子:

Class myclass {
    public void Request(@Intercept String t, String u) {
        // ...
    }
}

截取截取注释的方面:

@Aspect
class someAspect {
    @Intercept
    @Around("execution(public * * (@Interceptor (*), ..))")
    public void capture(ProceedingJoinPoint pjp) {
        // ...
    }
}

然而,我的方面是基于带注释的参数进行拦截。但我希望方面能够拦截参数t包含的特定值的方法请求。

例如,如果t==“t1”,则必须截取该方法,否则不能截取。

我想知道是否可以在AeyJ(与Spring AOP结合使用)中做到这一点。

共有1个答案

白浩荡
2023-03-14

实际上,您的代码存在一些问题(我只是重新格式化了它,因此它至少是可读的):

  • Java类名通常用驼峰大小写,即MyClass某些方面而不是myclass某些方面
  • Java中的方法名称以小写字符开头,即Request而不是Request
  • 您提到了两个注释@Intercept@Interceptor。从现在开始,我将假设实际上我们正在处理的只是一个名为@Intercept的注释,好吗?
  • 您还使用@Intercept注释了方面的建议,但我想这不是有意的,是吗?如果拦截建议正在拦截自己,它可能会导致另一个切入点中的无限递归...

至于您的实际问题,那么答案是:某种程度上,但不是静态地在切入点内(因为参数仅在运行时确定),而是动态地,也在运行时。您有两种选择:

选项A:if-其他在建议代码中

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Intercept {}
package de.scrum_master.app;

public class Application {
    public static void one(@Intercept String string) {}
    public static void two(String string, String string2) {}
    public static void three(@Intercept String string, int i, int j) {}

    public static void main(String[] args) {
        one("foo");
        two("foo", "bar");
        three("foo", 11, 22);

        one("bingo");
        two("bingo", "bongo");
        three("bingo", 33, 44);
    }
}
package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class InterceptorAspect {
    @Pointcut("execution(public * *(@de.scrum_master.app.Intercept (*), ..)) && args(text, ..)")
    public static void normalPointcut(String text) {}

    @Around("normalPointcut(text)")
    public Object capture(ProceedingJoinPoint thisJoinPoint, String text) {
        if (text != "bingo")
            return thisJoinPoint.proceed();
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs())
            System.out.println("  " + arg);
        // Do something before calling the original method
        Object result = thisJoinPoint.proceed();
        // Do something after calling the original method
        return result;
    }
}

选项B:使用切入点

if()切入点是一种静态方法,根据要测试的动态条件返回布尔值。重构方面如下所示:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class InterceptorAspect {
    @Pointcut("if() && execution(public * *(@de.scrum_master.app.Intercept (*), ..)) && args(text, ..)")
    public static boolean conditionalPointcut(String text) {
        return text != "bingo";
    }

    @Around("conditionalPointcut(text)")
    public Object capture(ProceedingJoinPoint thisJoinPoint, String text) {
        System.out.println(thisJoinPoint);
        for (Object arg : thisJoinPoint.getArgs())
            System.out.println("  " + arg);
        // Do something before calling the original method
        Object result = thisJoinPoint.proceed();
        // Do something after calling the original method
        return result;
    }
}

如您所见,动态的、基于参数的条件已移入切入点,它不再是具有空体的val方法,而是返回参数检查结果的布尔方法。此外,切入点表达式前面有一个if()

控制台日志:

两种方面变体的控制台输出完全相同:

execution(void de.scrum_master.app.Application.one(String))
  foo
execution(void de.scrum_master.app.Application.three(String, int, int))
  foo
  11
  22

 类似资料:
  • 我最近用aspectJ和spring-aop添加了AOP到我现有的spring项目中。目标是实际截获控制器调用以修改它们发回的响应,以便将一些值绑定到此响应,我不想手动添加到每个控制器中,例如最终用户使用的实际令牌的到期日期(无论如何我都无法在控制器中显示它)。实际上,在开始单元测试之前,我一直设法让它工作: 在我的单元测试中,我使用java中的反射特性直接调用我的控制器方法,然后复制通常的过程(

  • 我试图让aspectj拦截带注释的方法: 我删除了!为了简洁起见,在(InterceptMeAspect)内,但它并没有拦截太多。如果我删除注释约束(在(@InterceptMe*)内),它可以工作,但会拦截所有内容,这会造成一个大问题。 输出字节码似乎有完整的注释,所以我希望注释标准匹配。我正在或试图进行编译时编织。这很重要,因为我有另一个方面确实使用上面相同的方法工作。我怀疑该方面正在搞乱这个

  • 我正在使用Spring并试图用AspectJ编写示例应用程序。我需要学习如何拦截静态方法调用。在我的示例中,我尝试截取main方法,如下所示: Spring配置文件: 主要方法: 协会本身: 但是当我运行应用程序时,唯一的字符串正在打印。

  • 我正在尝试使用来做同样的事情,现在我使用哪个注释来捕获相关的对象,切入点表达式应该是什么?我尝试了,但这是一个void方法,如何捕获该方法的参数?我是AOP的初学者,所以如果这个问题太琐碎,请原谅。 解决方案:使用spring AOP获取方法参数?

  • 我的情况如下:我有一个loggingapect,其中有几个切入点与我的主应用程序中的特定方法执行相匹配。相应的建议机构基本上看起来都很相似,导致大量代码重复: 不过也有一些变化。有时是切入点 经常发生的事情是我手动告诉记录器 在打印第一条消息后,即在调用procedue()之前,增加缩进级别,并且 在打印最终消息之前(如果打印了任何消息),即直接在返回后降低缩进级别 我的想法是,我想用一个切入点编