java - 如何对带注释的方法的每个方法调用执行某些操作?

标签 java spring annotations aspectj

我想用Java编写一个注解,它在执行注解方法之前和之后执行一些操作,类似于Spring中使用方面可以完成的操作。

我已经尝试过 Spring 方面,但它仅适用于 Bean ( as this guy here mentioned ),并且我希望保持独立于 Spring 框架。

一个将字符串写入控制台的简单类:

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

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

相关注释:

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 {}

我需要类似的东西(从 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;
}

我想要以下输出:

Hello

How are you?

world!

编辑:

我创建了以下方面(没有注释),但它不起作用

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

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

我的错误在哪里?

最佳答案

假设您使用 AspectJ 编译器成功编译了切面,它应该可以与您使用的代码一起工作,只是它会记录所有方法执行,即 main(..),因此您会在“How are you?”之前和之后两次查看方面的输出。如果您没有看到任何内容,则可能是您在设置构建系统时犯了错误。

您应该更改切入点以实际限制记录到带注释的方法:execution(* *(..)) && @annotation(Hello)。此外,如果您的周围建议具有 void 返回类型,则日志记录将无法使用非 void 方法。因此,您应该使用 Object 返回类型并实际返回 proceed() 的结果。

我还强烈建议您不要盲目地使用像 AspectJ 这样强大的工具,而且在使用之前先研究一些文档。很明显,你还没有这样做,或者只是非常草率地这样做。然后你就会得到一个使用工具的能力不强的用户的效果。;-)

这是我的 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;
  }
}

控制台日志:

Hello
How are you?
world!

关于java - 如何对带注释的方法的每个方法调用执行某些操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56565631/

相关文章:

java - 如何修复Hibernate的配置文件?

java - 如何使用 Java 配置将 Jasypt 与 Spring 4 应用程序集成?

java - spring-security 解耦角色和权限

具有可变段数的 Spring 路径

java - 在 Javax.package 或替代方案中等效的 Hibernate @NotEmpty 注解

java - 如何在 ContainerRequestFilter 中检索请求的匹配资源

java - JPA 多对多和权威列表

java - 如何从 Twitter API Java JSON 获取所有 url 照片

java - 我的 DataSource Bean 做错了什么

swift - 将注释标题传递给 View Controller (快速)