【问题标题】:Create Pointcut for Spring AOP annotation to put annotation on class and execute advice on every method in class为 Spring AOP 注释创建切入点以将注释放在类上并在类中的每个方法上执行建议
【发布时间】:2020-08-21 05:14:56
【问题描述】:

我希望在类级别有注释,它将在带注释的类中对每个方法执行建议。 这有可能吗?

示例:我想用 @DoSomethingForMe 注释 OmniDemoService,并且我希望 method1method2 都记录“看看我" 执行前

这个例子不起作用,我不知道为什么。当我将 Pointcut 转换为 Around 并仅将其与注释一起使用时(还将注释 ElementType 更改为方法),一切都在方法级别上工作。 所以我认为这是错误定义的Pointcut。

注释:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoSomethingForMe {
}

建议:

@Aspect
@Component
public class DoSomethingForMeAdvice {

    private static final Logger logger = LoggerFactory.getLogger(DoSomethingForMeAdvice.class);

    @Pointcut("execution(public * *(..)) && @annotation(DoSomethingForMe)")
    public void anyAnnotatedMethod() {
    }

    @Before("anyAnnotatedMethod()")
    public void acquireExecution() {
        logger.info("look at me");
    }
}

用法:

@Service
@DoSomethingForMe
public class OmniDemoService {

    private static final Logger logger = LoggerFactory.getLogger(OmniDemoService.class);

    public void method1() {
            logger.info("---1---");
    }
    
    public void method2() {
            logger.info("---2---");
    }
}

【问题讨论】:

  • 是的,这是可能的,我不太了解实际问题。你有什么问题?
  • 这对我不起作用。可能切入点没有定义好。
  • 这可能是一个很好的阅读:baeldung.com/spring-aop-annotation
  • 这只是对@Around 方法级别建议用法的简单说明
  • 是的,我知道。你想说啥?您是否尝试过复制该配置、更改目标类型和更改注释位置?

标签: java spring aspectj spring-aop


【解决方案1】:

您的问题是您将切入点定义与建议混淆了。

Pointcut 正在瞄准,advice 执行实际的 WhatYouWantToBeExecuted。比如说

@Pointcut("@annotation(com.omnidemo.advice.DoSomethingForMe)")
public void anyAnnotatedMethod() {
}


@Before("anyAnnotatedMethod()")
public void logMethodCall(JoinPoint jp) {
    String methodName = jp.getSignature().toShortString();
    logger.info("Executing: " + methodName);
}

【讨论】:

  • 你是对的。那是因为我使用了@Around,它结合了两者。但是,这仍然不能解决我的问题如果我这样做 @Pointcut("execution(public * *(..)) && @annotation(LimitExecutionRate)") public void anyAnnotatedMethod() { } @Before("anyAnnotatedMethod()" ) public void acquireExecution() { logger.info("看看我"); rateLimiter.acquire(); } 它不会再工作了
  • 你能显示更新的代码吗?还有目标类?
  • 哦,我已经看到了,因为您已经注释了需要在其中使用的类(我直接想到了方法),如下所示:@Pointcut("@within(com.omnidemo.advice.DoSomethingForMe)")
  • 太棒了。有用。谢谢 :D 它需要 F-ing 内
【解决方案2】:

问题的解决方法是使用withinfor切入点

@Pointcut("@within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}

@Before("anyAnnotatedMethod()")
public void acquireExecution() {
    logger.info("look at me");
}

@J Asgarov 在 cmets 中提供的解决方案

【讨论】:

  • 也可以捕获非公共方法
  • 和构造函数、静态初始化器和... ANY 代码。
  • @Hawk,我认为将@within&& execution(public * *(..)) 结合起来很简单。 OP 已经在他的问题中使用了它,他唯一弄错的是使用 @annotation 而不是 @within。您的答案中更好的是您使用完全限定的类名作为注释,除非偶然或设计注释恰好与方面位于同一包中,否则这是必要的。 @this@target 的问题在于,它们在工作时会在运行时进行评估,因此可能比在编译时确定的 @within 慢。
  • 这不是微不足道的,因为在给定的代码(anyAnnotatedMethod)中明确没有提到执行连接点。如果是的话,那好吧。 (尽管我认为可能会在方法中捕获字段设置/获取连接点。)运行时评估是一个好点!但我还添加了另一个选项来定义带注释的类型,它应该是编译时的。
  • 我说OP的问题已经使用execution(..) && ...,我不是在说这个答案。所以我认为 OP 已经知道如何组合切入点,这将使他添加它变得微不足道。
【解决方案3】:

查看AspectJ quick reference@annotation() 的评价:

主题具有类型注释的任何连接点 SomeAnnotation

您使用了@annotation(DoSomethingForMe),但方法执行的“subject”是一个方法。所以这意味着 any 方法注释 @DoSomethingForMe。

使用@this(DoSomethingForMe)@target(DoSomethingForMe)

感谢kriegaex 指出@this@target 必须在运行时进行评估,这会严重污染代码库(即检查每个方法)。所以下一个方法更好:


如果您查看 AspectJ 手册中关于 type patterns 的部分,您将看到您可以直接注释类型。还请记住使用完全限定的类名。那就是:

execution(public * (@com.path.DoSomethingForMe *).*(..))

另外,如果你有这么简单的切入点,不需要重用,我想你可以放弃额外的方法,直接在advice中使用:

@Before("execution(public * (@com.path.DoSomethingForMe *).*(..))")

它说:“在执行带有@com.path.DoSomethingForMe 注释的类型的任何公共方法之前”,其中“在方法执行之前”的意思是“在方法内部,在开始时”。


或者,如果这个切入点对你来说有点过于复杂,你可以像这样将注解匹配和方法匹配分开,正如J Asgarov 在他的评论中所建议的那样:

@Before("execution(public * *(..)) && @within(com.path.DoSomethingForMe)")

【讨论】:

  • 我决定让您的答案更具可读性,修复和美化一些链接,并纳入@within 建议。我认为现在答案包含所有相关信息和一些可供选择的替代解决方案,并且应该被 OP 接受。我希望你不介意我弄乱你的答案。如果出于某种原因您不喜欢它,请随时恢复。但我真的不希望自己的答案归功于所有相关信息,因为您和 J Asgarov 已经提供了所有相关信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多