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

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

问题描述

我一直试图弄清楚 around adviceAspectJ 中的作用.

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,并且可以注入新行为beforeafter,以及代替那个joinpoint.proceed 是一个特殊的功能,它允许 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 支持的 advice 类型( beforeafteraround),around advice 是唯一允许返回一个值和/或使用 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

但是,让我们添加一些around 建议:

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("Before setting width");;
  2. 执行joinpoint两次(调用方法setWidth两次),从w 到 w + 100;
  3. 在调用该方法之后添加语句 System.out.println("After setting width");.
  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("Before getting Height");System.out.println("After getting Height"); 分别.此外,将 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)的调用code> 由语句 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); 

    }
}

这只是 advice around 如何工作的一个小例子,并不意味着你应该复制这个例子中所做的事情,并且不准确展示编织过程是如何在幕后发生的.

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天全站免登陆