java-如何使用Spring AOP或AspectJ拦截给定方法中的每个方法调用

 class Test {

@override
public String a(){
b();
d();
}


private String b() {
c();
}

private String c(){
d();
}
private String d(){}

}

我想拦截从重写方法A()调用的Test类的每个方法,并想知道每个方法(如b(),c())在分别处理一些业务逻辑时花了多少时间.

如何使用Spring AOP或Aspectj实现它?

解决方法:

为了

>融入私有方法,
>在一个类中处理自调用,
>动态确定控制流并将拦截仅限制为您的接口方法直接或间接调用的方法

您需要按照Spring手册中的说明从Spring AOP(基于代理,很多限制,速度较慢)切换到AspectJ using LTW (load-time weaving).

这是纯AspectJ(没有Spring,只有Java SE)中的示例,可以轻松满足您的需求:

样例界面

package de.scrum_master.app;

public interface TextTransformer {
  String transform(String text);
}

类实现接口,包括主要方法:

如您所见,我制作了一个像您一样的示例,并且还使这些方法花费时间,以便以后在方面进行一些测量:

package de.scrum_master.app;

public class Application implements TextTransformer {
  @Override
  public String transform(String text) {
    String geekSpelling;
    try {
      geekSpelling = toGeekSpelling(text);
      return toUpperCase(geekSpelling);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }

  }

  private String toGeekSpelling(String text) throws InterruptedException {
    Thread.sleep(100);
    return replaceVovels(text).replaceAll("[lL]", "1");
  }

  private String replaceVovels(String text) throws InterruptedException {
    Thread.sleep(75);
    return text.replaceAll("[oO]", "0").replaceAll("[eE]", "Ɛ");
  }

  private String toUpperCase(String text) throws InterruptedException {
    Thread.sleep(50);
    return text.toUpperCase();
  }

  public static void main(String[] args) throws InterruptedException {
    System.out.println(new Application().transform("Hello world!"));
  }
}

方面:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import static java.lang.System.currentTimeMillis;

@Aspect
public class TimingAspect {
  @Around("execution(* *(..)) && cflow(execution(* de.scrum_master.app.TextTransformer.*(..)))")
  public Object measureExecutionTime(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    long startTime = currentTimeMillis();
    Object result = thisJoinPoint.proceed();
    System.out.println(thisJoinPoint + " -> " + (currentTimeMillis() - startTime) + " ms");
    return result;
  }
}

控制台日志:

execution(String de.scrum_master.app.Application.replaceVovels(String)) -> 75 ms
execution(String de.scrum_master.app.Application.toGeekSpelling(String)) -> 189 ms
execution(String de.scrum_master.app.Application.toUpperCase(String)) -> 63 ms
execution(String de.scrum_master.app.Application.transform(String)) -> 252 ms
HƐ110 W0R1D!

您还可以通过仅将切入点从cflow()更改为cflowbelow()来排除transform(..)方法:

@Around("execution(* *(..)) && cflowbelow(execution(* de.scrum_master.app.TextTransformer.*(..)))")

那么控制台日志就是:

execution(String de.scrum_master.app.Application.replaceVovels(String)) -> 77 ms
execution(String de.scrum_master.app.Application.toGeekSpelling(String)) -> 179 ms
execution(String de.scrum_master.app.Application.toUpperCase(String)) -> 62 ms
HƐ110 W0R1D!

希望这就是您想要的.很难说,因为您的描述有些含糊.顺便说一句,请务必阅读AspectJ和/或Spring AOP手册.

上一篇:java-AspectJ EDT-Checker代码问题


下一篇:使用Spring Boot和AspectJ实现方法跟踪基础结构