简体   繁体   English

如何在带注释的方法的每个方法调用上执行某些操作?

[英]How do I perform something on each method call of an annotated method?

I want to write an annotation in Java, which executes something before and after execution of the annotated method, similar to what can be done in Spring with aspects. 我想用Java编写注释,该注释在执行带注释的方法之前和之后执行某些操作,类似于Spring在各个方面可以完成的操作。

I've already tried a Spring aspect, but it only works for Beans ( as this guy here mentioned ) and I want to stay independent from the Spring framework. 我已经尝试过Spring方面,但是它仅适用于Beans( 正如这里提到的 ),并且我想独立于Spring框架。

A simple class that writes a String to the console: 一个简单的类,将一个String写入控制台:

public class Main {
    public static void main(String[] args) {
        say("How are you?");
    }

    @Hello
    private static void say(String s) {
        System.out.println(s);
    }
}

The associated annotation: 关联的注释:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Hello {}

And I need something like (deduced from the Spring aspect) 我需要类似的东西(从Spring方面推导)

public Object process(ProceedingJoinPoint proceedingJoinPoint) {
    System.out.println("Hello");
    Object proceed = null;
    try {
        proceed = proceedingJoinPoint.proceed();
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    System.out.println("world!");
    return proceed;
}

I want the following output: 我想要以下输出:

Hello 你好

How are you? 你好吗?

world! 世界!

Edit: 编辑:

I created the following Aspect (without annotations), but it does not work 我创建了以下Aspect(没有注释),但是它不起作用

@lombok.extern.java.Log
public aspect Log {
    pointcut methodExecuted():execution(* **(..));

    void around(): methodExecuted() {
        log.info("Hello");
        proceed();
        log.info("world!");
    }
}

Where is my mistake? 我的错误在哪里?

Assuming that you successfully compiled your aspect with the AspectJ compiler, it should work with the code you used, only that it would log all method executions, ie also main(..) , so you would se the aspect's output twice before and after "How are you?". 假设您使用AspectJ编译器成功编译了方面,那么它应该可以与您使用的代码一起使用,只是它将记录所有方法的执行,即main(..) ,因此您在“你好吗?”。 If you don't see anything probably you made a mistake in setting up your build system. 如果看不到任何内容,则可能是在设置构建系统时出错了。

You should change the pointcut to actually limit logging to annotated methods: execution(* *(..)) && @annotation(Hello) . 您应该更改切入点,以将日志实际限制为带注释的方法: execution(* *(..)) && @annotation(Hello) Furthermore if your around advice has a void return type, logging will not work with non-void methods. 此外,如果您的周围建议具有空返回类型,则日志记录将不适用于非空方法。 So you should rather use a return type of Object and actually return the result of proceed() . 因此,您应该使用Object的返回类型,而实际上返回proceed()的结果。

I also strongly urge you to not just blindly wield a powerful tool like AspectJ but also study some documentation before you do. 我也强烈敦促您不仅盲目地使用诸如AspectJ之类的强大工具,还应该在使用前先学习一些文档。 It is quite obvious that you have not done so or only very cursorily. 很明显,您还没有这样做或者只是很粗略地做到了。 Then you get the effect of being a not-so-capable-user with a tool. 然后,您将获得使用工具的能力不强的用户的效果。 ;-) ;-)

Here is my MCVE : 这是我的MCVE

package de.scrum_master.app;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface Hello {}
package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    say("How are you?");
  }

  @Hello
  private static void say(String s) {
    System.out.println(s);
  }
}
package de.scrum_master.aspect;

import de.scrum_master.app.Hello;

public aspect LoggingAspect {
  pointcut methodExecuted() : execution(* *(..)) && @annotation(Hello);

  Object around(): methodExecuted() {
    System.out.println("Hello");
    Object result = proceed();
    System.out.println("world!");
    return result;
  }
}

Console log: 控制台日志:

Hello
How are you?
world!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM