围绕建议并继续调用:aspectJ,它是如何工作的?

around advice and proceed call: aspectJ, how it works?

我一直在努力弄清楚 around 建议 AspectJ.

中的作用

不像之前建议之后那么简单。有人可以简要介绍一下 around 建议的作用,以及 proceed 关键字的目的是什么吗?

非常非正式地,around建议拦截给定的连接点,并且可以注入 新行为 before, after, and instead of that joinpointproceed 是一个特殊的 特征 允许 around 建议 继续执行 joinpoint .

来自 AspectJ 支持的 advice 类型(即, beforeafteraround), around advice 是唯一允许 return 一个值 and/or 使用 proceed。这使得 around advice 可以多次执行相同的 joinpoint,或者根本不执行。此外,您甚至可以使用不同的上下文执行拦截的 joinpoint例如,更改方法参数的值)。可以找到更多详细信息 here.

让我们以一些代码为例。想象一个名为 Rectangle:

的 class
public class Rectangle {
    private double width, height;

    public void setWidth(double w) {
           System.out.println("Set Width " + w);
           this.width = w;
    }
 
    public void setHeight(double h) {
           System.out.println("Set height " + h);
           this.height = h;
    }

    
    public double getWidth() {return this.width;}
    public double getHeight() {return this.height; }
}

以及调用 class 的方法:

public class Main {
    
    public static void main(String[] args) {
        Rectangle s = new Rectangle();
        s.setWidth(10);
        s.setHeight(2);
        double w =  s.getWidth();
        double h = s.getHeight()
        System.out.println("Width " + w + " Height " + h);
    }
}

如果你运行上面的代码,你将得到以下输出:

Set Width 10.0
Set Height 2.0
Width 10.0 Height 2.0

但是,让我们添加一些 around 建议 到组合中:

 void around(double w) : call(public void  Rectangle.setWidth(double)) && args(w){
      System.out.println("Before setting width");
      proceed(w + 100);
      proceed(w + 100);
      System.out.println("After setting width");
 }
 
 double around() : call(public double  Rectangle.getHeight()){
        System.out.println("Before getting Height");
        double h = proceed();
        System.out.println("After getting Height");
        return h + 200;
 }

 void around(double w) : call(public void  Rectangle.setHeight(double)) && args(w){
        System.out.println("No Height setting");
  }

现在你将得到输出:

Before setting width
Set Width 110.0
Set Width 110.0
After setting width
No Height setting
Before getting Height
After getting Height
Width 110.0 Height 200.0

那么让我们一步一步地尝试理解输出结果,好吗?!。第一个advice会拦截classRectangle中对方法public void Rectangle.setWidth(double)的调用。并且会:

  1. 在该方法调用之前添加语句System.out.println("Before setting width");
  2. 执行joinpoint两次(调用方法setWidth两次),修改其原始参数从ww + 100;
  3. 在该方法调用后添加语句System.out.println("After setting width");

因此,原来的代码现在等同于:

public class Main {
    
    public static void main(String[] args) {
        Rectangle s = new Rectangle();
        System.out.println("Before setting width");  // <--- new lines
        s.setWidth(10+100);
        s.setWidth(10+100);
        System.out.println("After setting width");   // <--- new lines
        s.setHeight(2);
        double w =  s.getWidth();
        double h = s.getHeight()
        System.out.println("Width " + w + " Height " + h);
    }
}

第二个 around advice 将拦截对方法 public double Rectangle.getHeight() 的调用,在这些方法调用之前和之后注入语句 System.out.println("Before getting Height");System.out.println("After getting Height");。此外,会将 200 添加到 getHeight 编辑的值 return 中。因此,

public class Main {
    
    public static void main(String[] args) {
        Rectangle s = new Rectangle();
        System.out.println("Before setting width"); 
        s.setWidth(10+100);
        s.setWidth(10+100);
        System.out.println("After setting width");  
        s.setHeight(2);
        double w =  s.getWidth();
        System.out.println("Before getting Height"); // <-- new lines
        double h = s.getHeight() + 200 // <-- new behaviour 
        System.out.println("After getting Height"); // <-- new lines
        System.out.println("Width " + w + " Height " + h); 

    }
}

最后,第三个around建议替换对方法public void Rectangle.setHeight(double)的调用System.out.println("No Height setting");。因此:

public class Main {
    
    public static void main(String[] args) {
        Rectangle s = new Rectangle();
        System.out.println("Before setting width"); 
        s.setWidth(10+100);
        s.setWidth(10+100);
        System.out.println("After setting width");
        System.out.println("No Height setting"); // <-- new line  
        double w =  s.getWidth();
        System.out.println("Before getting Height");
        double h = s.getHeight() + 200 // <-- new behaviour 
        System.out.println("After getting Height");
        System.out.println("Width " + w + " Height " + h); 

    }
}

这只是 建议 around 工作原理的一个小例子,并不意味着您应该复制本示例中所做的相同操作,并且没有准确显示 编织 过程是如何在幕后发生的。