我正在学习Spring AOP ,我对我的学习资料中发现的排名有以下疑问。
请考虑以下切入点:执行(@ com.myapp.MyCustomAnnotation void *(..))。究竟意味着什么?
它给了我以下答案,在我看来是一个愚蠢的奇怪(使用我对AOP如何工作的知识)。它说:
这将选择代表voiud方法的联合点 由 @ com.myapp.MyCustomAnnotation 注释注释。
好的,这意味着使用 AOP 我可以指定何时执行使用特定注释注释的特定方法?是对的还是我错过了什么?
因此,如果先前的断言是正确的,则意味着(例如)我还可以指定类似的内容:"当执行由 @RequestMapping注释的控制器方法时(" / listAccounts&#34)? (这意味着,当控制器处理HttpRequest朝向 / listAccounts 资源执行类似的操作时:
execution(@RequestMapping("/listAccounts") * *(..))
我可以这样做吗?
答案 0 :(得分:1)
Spring正在使用AspectJ切入点表达式语言(https://eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html)
应用你的切入点表达式意味着拦截所有带有'void'返回类型的名称和参数列表的方法调用,只要该方法使用@ com.myapp.MyCustomAnnotation进行注释即可。
虽然使用Annotation-Parameters无法匹配Join-Points,所以你的第二个Pointcut-Expression无效。
答案 1 :(得分:1)
您无法在切入点中明确指定注释的参数。相反,您可以设置切入点以使用@RequestMapping
注释捕获所有方法,然后从方法中检索注释并检查该值是否与端点匹配。例如:
@PointCut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void requestMapping() {}
@Before("requestMapping()")
public void handleRequestMapping(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String mapping = method.getAnnotation(RequestMapping.class).value()[0];
if (mapping.equals("/listAccounts") {
// do something
}
}
答案 2 :(得分:0)
AndréR。的答案是不正确的,因为 可以限制与参数值的注释匹配,但是有一个限制:它只适用于简单类型,如字符串,整数和类,而不是字符串数组左右。但在您的具体示例中,Spring注释@RequestMapping
的值类型为String[]
,请参阅Javadoc。让我们假设你有这种情况:
<强>注释:强>
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;
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int value();
String name() default "";
Class<?> type() default Object.class;
}
驱动程序应用程序:
这里我们有一个应用程序,其中有几个方法由Spring注释@RequestMapping
和我们自制的注释@MyAnnotation
注释:
package de.scrum_master.app;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
public class Application {
@RequestMapping("/listAccounts")
@MyAnnotation(11)
public void doSomething() {}
public void doSomethingElse() {}
@RequestMapping(value = {"/listAccounts","/another/method"}, name = "Newton")
@MyAnnotation(value = 22, type = String.class)
public void foo() {}
@RequestMapping(value = "/listAccounts", method = RequestMethod.POST, name = "Einstein")
@MyAnnotation(value = 11, name = "John Doe", type = String.class)
public void bar() {}
@RequestMapping(value = "/listCustomers", method = RequestMethod.GET, name = "Einstein")
@MyAnnotation(value = 22, name = "Jane Doe")
public void zot() {}
@RequestMapping(value = "/listAccounts", produces = {"application/json","application/xml"}, consumes = "text/html", name = "Newton")
public void baz() {}
public static void main(String[] args) {
Application application = new Application();
application.doSomething();
application.doSomethingElse();
application.foo();
application.bar();
application.zot();
application.baz();
}
}
注释匹配方面:
package de.scrum_master.aspect;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.web.bind.annotation.RequestMapping;
import de.scrum_master.app.MyAnnotation;
@Aspect
public class AnnotationParameterMatcher {
// Match *all* methods annotated by @RequestMapping
@Before("execution(* *(..)) && @annotation(requestMapping)")
public void logRequestMapping(JoinPoint thisJoinPoint, RequestMapping requestMapping) {
// Print joinpoint and annotation
System.out.println(thisJoinPoint + " -> " + requestMapping);
}
// Match *all* methods annotated by @RequestMapping
@Before("execution(* *(..)) && @annotation(requestMapping)")
public void logMatchingValue(JoinPoint thisJoinPoint, RequestMapping requestMapping) {
// Only print if value array contains "/listAccounts"
if (Arrays.asList(requestMapping.value()).contains("/listAccounts"))
System.out.println(" value contains '/listAccounts'");
}
// Match *all* methods annotated by @RequestMapping and bind 'name' parameter
@Before("execution(* *(..)) && @annotation(RequestMapping(name))")
public void logName(JoinPoint thisJoinPoint, String name) {
System.out.println(" name = '" + name + "'");
}
// Match methods annotated by @MyAnnotation with value=11
@Before("execution(@MyAnnotation(value=11) * *(..))")
public void logName(JoinPoint thisJoinPoint) {
System.out.println(" @MyAnnotation(value=11) detected");
}
// Match methods annotated by @MyAnnotation with 3 specific parameter values
@Before("execution(@MyAnnotation(value=11, name=\"John Doe\", type=String.class) * *(..)) && @annotation(myAnnotation)")
public void logName(JoinPoint thisJoinPoint, MyAnnotation myAnnotation) {
System.out.println(" " + myAnnotation);
}
}
控制台输出:
execution(void de.scrum_master.app.Application.doSomething()) -> @org.springframework.web.bind.annotation.RequestMapping(headers=[], method=[], name=, produces=[], params=[], value=[/listAccounts], consumes=[])
value contains '/listAccounts'
name = ''
@MyAnnotation(value=11) detected
execution(void de.scrum_master.app.Application.foo()) -> @org.springframework.web.bind.annotation.RequestMapping(headers=[], method=[], name=Newton, produces=[], params=[], value=[/listAccounts, /another/method], consumes=[])
value contains '/listAccounts'
name = 'Newton'
execution(void de.scrum_master.app.Application.bar()) -> @org.springframework.web.bind.annotation.RequestMapping(headers=[], method=[POST], name=Einstein, produces=[], params=[], value=[/listAccounts], consumes=[])
value contains '/listAccounts'
name = 'Einstein'
@MyAnnotation(value=11) detected
@de.scrum_master.app.MyAnnotation(name=John Doe, type=class java.lang.String, value=11)
execution(void de.scrum_master.app.Application.zot()) -> @org.springframework.web.bind.annotation.RequestMapping(headers=[], method=[GET], name=Einstein, produces=[], params=[], value=[/listCustomers], consumes=[])
name = 'Einstein'
execution(void de.scrum_master.app.Application.baz()) -> @org.springframework.web.bind.annotation.RequestMapping(headers=[], method=[], name=Newton, produces=[application/json, application/xml], params=[], value=[/listAccounts], consumes=[text/html])
value contains '/listAccounts'
name = 'Newton'