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

切入点表达式将@ModelAttory解析为方法参数

刘嘉木
2023-03-14

我在@controllerAdvice中定义了一个@ModelAttribute(键),我在多个控制器方法中使用相同的模型属性作为方法参数,因为(键)在所有控制器中都可用。

我像这样在控制器类中添加属性(key)。

@RequestMapping(value = "/", method = RequestMethod.GET)
public String list(final Model model,@ModelAttribute("key") final boolean key) { 
...
...
}

我想截取所有以@ModelAttory("key")作为方法参数的控制器方法。

我的方面文件看起来像这样。

@Component
@Aspect
@EnableAspectJAutoProxy
public class myAspectclass {

@Pointcut("execution(public * *(.., @org.springframework.web.bind.annotation.ModelAttribute(boolean key)))")
          public void methodWithAnnotatedParameter() {}

@Around("methodWithAnnotatedParameter()")
public String blahMethod(ProceedingJoinPoint PJP){

blah blah

....
}

但是我的服务器启动失败说

[tomcat:launch]由:java引起。lang.IllegalArgumentException:切入点格式不正确:字符位置97处应为“名称模式

[tomcat:launch]执行(public**(..,@org.springframework.web.bind.annotation.ModelAttribute(布尔键),…)

我无法理解这种情况下的错误。。。我在句法上做错了什么吗?

注意:我的模型属性(键)在参数列表中没有任何特定位置

引用此答案:

共有1个答案

莫骞仕
2023-03-14

这是一个独立的AspectJ示例(不是Spring应用程序,但方面语法应该相同)。

驱动程序应用:

如您所见,有几种方法带有和不带有参数注释,其中一种方法甚至带有两个带注释的参数(无论是否合理,但这只是一个示例)。

package de.scrum_master.app;

import java.util.Collection;
import java.util.Map;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;

public class Application {
  public String list(Model model, @ModelAttribute("key") boolean key) {
    return "x";
  }

  public String foo(Model model, @ModelAttribute("key") boolean key, @ModelAttribute(name = "key") String text) {
    return "x";
  }

  public String bar(@ModelAttribute(name = "key") int number) {
    return "x";
  }

  public String zot(Model model, @ModelAttribute("XXX") boolean key) {
    return "x";
  }

  public String baz(Model model, boolean key, String text) {
    return "x";
  }

  public String bla(@ModelAttribute("XXX") int number) {
    return "x";
  }

  public static void main(String[] args) {
    Model model = new Model() {
      @Override public Model mergeAttributes(Map<String, ?> arg0) { return null; }
      @Override public boolean containsAttribute(String arg0) { return false; }
      @Override public Map<String, Object> asMap() { return null; }
      @Override public Model addAttribute(String arg0, Object arg1) { return null; }
      @Override public Model addAttribute(Object arg0) { return null; }
      @Override public Model addAllAttributes(Map<String, ?> arg0) { return null; }
      @Override public Model addAllAttributes(Collection<?> arg0) { return null; }
    };
    Application application = new Application();
    application.list(model, true);
    application.foo(model, true, "hey");
    application.bar(11);
    application.zot(model, true);
    application.baz(model, true, "hey");
    application.bla(11);
  }
}

方面:

该方面将至少具有一个参数的所有方法执行与注释相匹配。如果您只想查找这些方法,而不考虑注释参数值,那么切入点就足够了。但是正如您所说,您只想匹配那些具有值的注释,我们需要使用反射来查看注释本身并过滤掉不需要的注释。

另一个复杂问题是,根据JavaDoc,参数名称和值是彼此的别名,即我们还需要检查这两个参数的值,以便完全正确。

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ModelAttribute;

@Aspect
@Component
public class ModelAttributeInterceptor {
  @Pointcut("execution(public * *(.., @org.springframework.web.bind.annotation.ModelAttribute (*), ..))")
  public void methodWithAnnotatedParameter() {}

  @Around("methodWithAnnotatedParameter()")
  public String blahMethod(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
    Annotation[][] annotationMatrix = methodSignature.getMethod().getParameterAnnotations();
    boolean foundModelAttribute = false;
    for (Annotation[] annotations : annotationMatrix) {
      for (Annotation annotation : annotations) {
        if (!(annotation instanceof ModelAttribute))
          continue;
        ModelAttribute modelAttribute = (ModelAttribute) annotation;
        if ("key".equals(modelAttribute.value()) || "key".equals(modelAttribute.name())) {
          if (!foundModelAttribute) {
            System.out.println(thisJoinPoint);
            foundModelAttribute = true;
          }
          System.out.println("  " + modelAttribute);
        }
      }
    }
    return (String) thisJoinPoint.proceed();
  }
}

控制台日志:

execution(String de.scrum_master.app.Application.list(Model, boolean))
  @org.springframework.web.bind.annotation.ModelAttribute(name=, value=key, binding=true)
execution(String de.scrum_master.app.Application.foo(Model, boolean, String))
  @org.springframework.web.bind.annotation.ModelAttribute(name=, value=key, binding=true)
  @org.springframework.web.bind.annotation.ModelAttribute(name=key, value=, binding=true)
execution(String de.scrum_master.app.Application.bar(int))
  @org.springframework.web.bind.annotation.ModelAttribute(name=key, value=, binding=true)
 类似资料:
  • 我在我的Scala项目中使用带有sbt-aspectj的AeyJ库。我正在尝试使用表达式编写: 但我有以下例外: 以下AspectJ教程介绍: 因此,通过注释样式,可以仅在@pointcut表达式中使用if()切入点。if()不能包含任何正文。然后,带注释的@切入点方法必须是公共静态布尔的形式,并且可以像往常一样使用形式绑定 可以在Scala方法上使用切入点中的if()表达式吗?

  • 我有一个lambda表达式,我希望能够传递和重用。代码如下: 这里的关键是,我希望能够将我在这里使用的lambda表达式传递到调用此代码的方法中,以便可以重用它。lambda表达式是我的。查询方法。我假设我想使用Action或Func,但我不太确定它的语法是什么,或者它是如何工作的。谁能给我举个例子吗?

  • 我有一个场景,我需要拦截一些子类方法,但我找不到合适的切入点表达式来这样做。 我有一个面向客户机的接口,它有一个方法。 当用户调用方法时,我希望截获方法。我可以很容易地截获,但是似乎没有什么能截获子类方法。我甚至尝试使用自定义注释来注释这些信息方法,但没有成功。到目前为止,我提出了以下方面 将设置为true或false也没有帮助。我知道AOP不能拦截私有子类方法,但这些是公共的。有可能做到这一点吗

  • 是否可以根据方法参数名称匹配切入点表达式? 例如,我想将所有方法与作为参数进行匹配。 我无法按数据类型进行匹配,因为它太宽了。 我知道我可以使用通配符匹配任何内容,例如执行(**(..)” 并检查方法体中的参数名称,但这似乎过多?

  • 我正在寻找一个JAVA库来解析 我的要求: 支持所有的值类型(例如int,双,布尔,String等) 支持所有已知的数学 有什么建议吗?

  • 问题内容: 可以说我已经编写了一个函数来评估简单的数学运算,并且在字符串中有一些用户输入,例如:“ 1 + [2 + [3 + 4]]”如何解析这些方括号并首先提取最里面的文本(3 + 4),对其求值,然后解析外部花括号(2 + 7)?我对Regex搜索和替换有基本的了解,但是我知道他们不会像这样进行递归。我想要一些基本的Java代码来执行此操作,如果可以避免的话,还不需要另一个jar / API