我需要使用aspectj修改遗留代码方法的返回类型。

class MyClass{
   public void processTracker(TrackInfo trackInfo) {
     if (isValid(this.getStatus()) {
        process(trackInfo);
     }
   }

  boolean isValid(Status status){
   ...
  }
}


我希望isValid方法通过TrackInfo对象的其他基于逻辑的状态(将参数传递给processTracker方法)返回true / false。

Aspecting processTracker方法将给我参数,但不会提供修改isValid返回值的选项

@Around("execution(* MyClass.processTracker(..))


方面isValid不允许我访问参数trackInfo

2个方面是不可能的,因为此代码在多线程中运行...
我没有使用Spring,也无法向旧代码添加自定义注释。

有任何想法吗?

最佳答案

实际上,您的问题很难理解,可能是因为您的英语水平不是特别好。特别是,我不知道为什么您认为多线程在这里会成为问题。也许您可以更详细地说明这一点。

无论如何,我在这里为您提供两种AOP解决方案:


如示例代码所示,如​​果process(TrackInfo)条件确实是if中的全部逻辑,则仅从方面直接调用processTracker(TrackInfo)。从语义上讲,您只需替换所拦截方法的整个逻辑即可。
如果processTracker(TrackInfo)中实际上存在更多逻辑,并且您的示例代码过于简化,例如外科医生,则需要用更细的刀剪掉,并应用AOP术语中通常被称为虫洞模式的内容。


应用程序+帮助程序类:

因为您的示例代码不完整,所以我不得不猜测并组成一个MCVE,下一次我希望您这样做是因为这实际上是您的工作,而不是我的。

package de.scrum_master.app;

public enum Status {
    VALID, INVALID
}


package de.scrum_master.app;

public class TrackInfo {
  private String info;

  public TrackInfo(String info) {
    this.info = info;
  }

  public String getInfo() {
    return info;
  }

  @Override
  public String toString() {
    return "TrackInfo(" + info + ")";
  }
}


package de.scrum_master.app;

import static de.scrum_master.app.Status.*;

public class MyClass {
  private Status status = VALID;

  public void processTracker(TrackInfo trackInfo) {
    if (isValid(getStatus()))
      process(trackInfo);
  }

  public void process(TrackInfo trackInfo) {
    System.out.println("Processing " + trackInfo);
  }

  private Status getStatus() {
    if (status == VALID)
      status = INVALID;
    else
      status = VALID;
    return status;
  }

  boolean isValid(Status status) {
    return status == VALID;
  }

  public static void main(String[] args) {
    MyClass myClass = new MyClass();
    myClass.processTracker(new TrackInfo("normal"));
    myClass.processTracker(new TrackInfo("whatever"));
    myClass.processTracker(new TrackInfo("special"));
  }
}


如您所见,我只是在每次调用时都将有效性从无效更改为有效,然后再返回,只是在运行main方法时获得不同的结果。

控制台日志为:

Processing TrackInfo(whatever)


到目前为止,一切都很好。不让我们假设,如果TrackInfo与字符串“ special”相匹配,我们要始终假设有效性检查的结果为true。

1.)processTracker(TrackInfo)的方面替换逻辑

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import de.scrum_master.app.MyClass;
import de.scrum_master.app.TrackInfo;

@Aspect
public class SimpleAspect {
  @Around("execution(* de.scrum_master.app.MyClass.processTracker(..)) && args(trackInfo) && target(myClass)")
  public void modifyValidityCheck(ProceedingJoinPoint thisJoinPoint, TrackInfo trackInfo, MyClass myClass) throws Throwable {
    if (trackInfo.getInfo().equalsIgnoreCase("special")) {
      // Kick off processing based on some special logic
      myClass.process(trackInfo);
    }
    else {
      // Proceed normally
      thisJoinPoint.proceed();
    }
  }
}


在这里,我们不需要知道有效性检查的结果,而仅在需要时直接调用process(TrackInfo)。日志输出更改为:

Processing TrackInfo(whatever)
Processing TrackInfo(special)


2.)虫眼图案解决方案

在这里,我们实际上将调用方法TrackInfo中的processTracker(TrackInfo)作为上下文信息拉到了isValid(Status status)中,因此如有必要,我们可以直接修改有效性检查结果。

package de.scrum_master.aspect;

import static de.scrum_master.app.Status.*;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import de.scrum_master.app.Status;
import de.scrum_master.app.TrackInfo;

@Aspect
public class WormholePatternAspect {
  @Pointcut("execution(* de.scrum_master.app.MyClass.processTracker(..)) && args(trackInfo)")
  public static void processTracker(TrackInfo trackInfo) {}

  @Pointcut("execution(* de.scrum_master.app.MyClass.getStatus())")
  public static void getStatus() {}

  @Around("getStatus() && cflow(processTracker(trackInfo))")
  public Status modifyValidityCheck(ProceedingJoinPoint thisJoinPoint, TrackInfo trackInfo) throws Throwable {
    if (trackInfo.getInfo().equalsIgnoreCase("special")) {
      // Return true based on some special logic
      return VALID;
    }
    else {
      // Proceed normally
      return (Status) thisJoinPoint.proceed();
    }
  }
}


控制台日志与第一个方面相同,但是如果processTracker(TrackInfo)中有更多逻辑,则其余部分也将被执行,而不是像第一个方面那样被切断(替换)。

随便你吧。如果适用,我建议使用更简单的解决方案。虫洞模式很优雅,但更难理解,并且由于cflow()而需要运行时调用栈分析,因此它也应该稍微慢一些。

关于java - 使用aspectJ根据调用方法的参数修改方法的返回类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54605457/

10-10 03:09