围绕建议并继续致电:AspectJ,它是如何工作的? [英] around advice and proceed call: aspectJ, how it works?

查看:64
本文介绍了围绕建议并继续致电:AspectJ,它是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图弄清 AspectJ 中的周围 建议的工作原理.

I've been trying to figure out what the around advice works in AspectJ.

这不像之前建议之后那样简单.有人可以简要介绍一下 around 建议的功能,以及 proceed 关键字的目的是什么?

It's not simple like the before and after advice. Could someone please give a brief introductory view of what the around advice does, and what is the purpose of the proceed keyword?

推荐答案

非常非正式地, around advice 会拦截给定的 joinpoint ,并且可以之前,之后注入 新行为,而不是连接. proceded 是一种特殊的功能,它允许 around advice 继续执行 joinpoint .

Very informally, an around advice intercepts a given joinpoint, and can inject new behavior before, after, and instead of that joinpoint. The proceed is a special feature that allows the around advice to continue the execution of the joinpoint.

由AspectJ支持的建议类型( 之前之后左右),则左右 建议是唯一允许返回一个值和/或使用 proceed .这使得 around advice 可以执行几次相同的 joinpoint ,或者根本不执行.此外,您甚至可以在不同的上下文中执行被拦截的 joinpoint (例如,更改方法参数的值).可以在此处中找到.

From the types of advice supported by AspectJ (i.e., before, after, and around), the around advice is the only one allowed to return a value and/or use the proceed. This makes it possible for an around advice to execute several times the same joinpoint, or not executed it at all. Furthermore, you can even execute the intercepted joinpoint with a different context (e.g., change the value of the method arguments). More details can be found here.

让我们使用一些代码作为示例.想象一个名为 Rectangle :

Let us use some code as an example. Imagine a class named 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; }
}

以及该类中的方法被调用:

and the methods of that class being called in:

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

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

If you run the code above, you will get the following output:

Set Width 10.0
Set Height 2.0
Width 10.0 Height 2.0

但是,让我们在混合中添加一些左右 建议:

However, let us add some around advices into the mix:

 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

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

So let us try to make sense out of that output, step-by-step, shall we?!. The first advice will intercept the call to the method public void Rectangle.setWidth(double) in the class Rectangle. And will:

  1. 在该方法的调用之前添加语句 System.out.println(设置宽度之前");
  2. 执行两次连接点(两次调用方法 setWidth ),并从 w 到 w + 100 ;
  3. 在该方法的调用之后添加语句 System.out.println(设置宽度后"); .
  1. add the statement System.out.println("Before setting width"); before the call of that method;
  2. execute the joinpoint twice (i.e., call the method setWidth twice), modifying its original parameter from w to w + 100;
  3. add the statement System.out.println("After setting width"); after the call of that method.

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

Consequently, the original code is now equivalent to:

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(在获得高度之前"); System.out.println(在获得高度之后"); .此外,会将 200 添加到 getHeight 返回的值中.因此,

The second around advice will intercept the calls to the method public double Rectangle.getHeight(), inject before and after those method calls the statements System.out.println("Before getting Height"); and System.out.println("After getting Height");, respectively. Moreover, will add 200 to the value returned by getHeight. Hence,

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 advice 替换对方法 public void Rectangle.setHeight(double)的调用语句 System.out.println("No Height setting"); .因此:

Finally, the third around advice will replace the call to the method public void Rectangle.setHeight(double) by the statement System.out.println("No Height setting");. Consequently:

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

    }
}

这只是建议 周围的工作原理的一小部分说明,并不意味着您应该复制在此示例中所做的相同操作,并且不能准确地复制展示编织过程是如何在后台进行的.

This is just a small illustration of how the advice around works, does not mean that you should replicate the same what was done in this example, and does not accurately show how the weaving process happens under the hood.

这篇关于围绕建议并继续致电:AspectJ,它是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆