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

时间:2018-04-16 17:55:43

标签: java aspectj modelattribute pointcut

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

我在控制器类中添加属性(键),如下所示。

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

我想拦截所有以@ModelAttribute("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] execution(public * *(..,@ org.springframework.web.bind.annotation.ModelAttribute(boolean key),..))

我无法理解这种情况下的错误......我在语法上做错了吗?

注意:我的ModelAttribute(key)在参数列表中没有任何具体位置

参考this回答:

1 个答案:

答案 0 :(得分:0)

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

驱动程序应用程序:

正如您所看到的,有几种方法有和没有@ModelAttribute参数注释,其中一种方法甚至带有两个带注释的参数(无论是否有意义,但它只是一个例子)。

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);
  }
}

<强>方面:

方面匹配具有至少一个带@ModelAttribute注释的参数的所有方法执行。如果您只想查找这些方法,切入点就足够了,无论注释参数值如何。但正如你所说,你只想匹配value = "key"的那些,我们需要使用反射来查看注释本身并过滤掉不需要的注释。

根据@ModelAttribute JavaDoc的另一个复杂因素,参数namevalue是彼此的别名,即我们还需要检查两个参数&#39;值,以使其完全正确。

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)