Warm tip: This article is reproduced from serverfault.com, please click

java-围绕建议并继续致电:AspectJ,它是如何工作的?

(java - around advice and proceed call: aspectJ, how it works?)

发布于 2020-12-11 15:24:09

我一直在尝试找出around 建议的用处AspectJ

这不像之前和之后的建议那样简单有人可以简要介绍一下around建议的用途以及proceed关键字的目的吗?

Questioner
red_rum
Viewed
0
dreamcrash 2020-12-12 06:55:35

非常非正式的around 咨询截取一个给定的连接点,并能注入新的行为,和而不是连接点proceed是一个特殊的功能,允许around 建议继续的执行joinpoint

从的类型的建议通过的AspectJ支持( beforeafteraround),该around 建议是唯一一个允许返回的值和/或使用proceed这样一来,around 建议就可以多次执行相同的联接点,或者根本不执行该联接点此外,你甚至可以在不同的上下文中执行拦截的连接点例如,更改方法参数的值)。可以在这里找到更多详细信息

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

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

并调用该类的方法:

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

因此,让我们尝试逐步了解该输出,对吧?第一个建议 将拦截public void Rectangle.setWidth(double)对类中方法的调用Rectangle还会:

  1. System.out.println("Before setting width");在该方法的调用之前添加语句
  2. 执行两次联结点两次调用该方法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 建议将拦截对public double Rectangle.getHeight()方法的调用,分别在这些方法调用语句System.out.println("Before getting Height");之前和之后注入System.out.println("After getting Height");而且,将添加200到返回的值getHeight因此,

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)statement代替对方法的调用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工作原理的一小部分说明,并不意味着你应该重复此示例中所做的操作,并且不能准确地显示机过程是如何进行的。