Spring AOP -带参数的注解

iqjalb3h  于 2023-03-16  发布在  Spring
关注(0)|答案(2)|浏览(180)

我在Spring Boot 中遇到了一个问题。我试图给一些RestController给予额外的功能,我试图用一些自定义注解来实现它。下面是一个例子。
我的注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
  String someArg();
}

我的方面:

@Aspect
@Component
public class MyAspect {
  @Around(
    value = "@annotation(MyCustomAnnotation)",
    argNames = "proceedingJoinPoint,someArg"
  )
  public Object addMyLogic(ProceedingJoinPoint proceedingJoinPoint, String someArg)
    throws Throwable
  {
    System.out.println(someArg);
    return proceedingJoinPoint.proceed();
  }
}

我的方法:

@MyCustomAnnotation(someArg = "something")
@GetMapping("/whatever/route")
public SomeCustomResponse endpointAction(@RequestParam Long someId) {
  SomeCustomResult result = someActionDoesNotMatter(someId);
  return new SomeCustomResponse(result);
}

主要基于文档(https://docs.spring.io/spring/docs/3.0.3.RELEASE/spring-framework-reference/html/aop.html-7.2.4.6建议参数),我很肯定,它应该工作。
我在这里,因为它不...
让我抓狂的是,即使是Intellij,当试图帮助处理argNames(空字符串-〉红色下划线-〉alt+enter -〉正确的argNames属性)时,也会给我这个,并保持红色...
基于这些文档,甚至不需要proceedingJoinPoint(没有它也不能工作):如果第一个参数属于连接点,则继续连接点...
在当前设置中,它显示“未绑定的切入点参数'someArg'”
在这一点上,我还应该注意到,如果没有args,它工作得很好。
实际上,我有两个问题:
1.为什么这不起作用?(这是很明显的)
1.如果我想给予一些控制器一些额外的功能,并且我想从外部参数化它,这是Spring Boot 中的正确模式吗?(对于python,用装饰器做这件事相当容易-我不太确定,我没有被类似的语法误导)
举一个例子(上面的例子很抽象):
我想创建一个@LogEndpointCall注解,路由的开发人员以后可以将它放在他正在开发的端点上
......然而,如果他能添加一个字符串(或者更可能是一个枚举)作为参数,那就太好了

@LogEndpointCall(EndpointCallLogEnum.NotVeryImportantCallWhoCares)

@LogEndpointCall(EndpointCallLogEnum.PrettySensitiveCallCheckItALot)

以便触发相同的逻辑,但使用不同的param -〉,并保存到不同的目的地。

yb3bgrhw

yb3bgrhw1#

注解属性不能直接绑定到通知参数,只需绑定注解本身并正常访问其参数即可:

@Around("@annotation(myCustomAnnotation)")
public Object addMyLogic(
  ProceedingJoinPoint thisJoinPoint,
  MyCustomAnnotation myCustomAnnotation
)
  throws Throwable
{
  System.out.println(thisJoinPoint + " -> " + myCustomAnnotation.someArg());
  return thisJoinPoint.proceed();
}

它会用Spring AOP打印出类似这样的东西

execution(SomeCustomResponse de.scrum_master.app.Application.endpointAction(Long)) -> something

AspectJ也是这样(因为AJ也知道调用连接点,而不仅仅是执行)

call(SomeCustomResponse de.scrum_master.app.Application.endpointAction(Long)) -> something
execution(SomeCustomResponse de.scrum_master.app.Application.endpointAction(Long)) -> something
5vf7fwbs

5vf7fwbs2#

如果你想让你的方法拦截那些考虑参数的方法,你必须在你的切入点表达式中明确指出,要让它在这里工作,你应该做的是:

@Around(
value = "@annotation(MyCustomAnnotation) && args(someArg)",
argNames = "someArg")

注意,我添加了**&& args(someArg),你可以添加任意多的参数,在argNames中你可以省略proceedingJoinPoint**。

相关问题