围绕建议并继续调用:aspectJ,它是如何工作的? [英] around advice and proceed call: aspectJ, how it works?
问题描述
我一直试图弄清楚 around
advice 在 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,并且可以注入新行为before,after,以及代替那个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 类型(即 before
、after
和 around
),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:
- 在调用该方法之前添加语句
System.out.println("Before setting width");
; - 执行joinpoint两次(即调用方法
setWidth
两次),从w
到w + 100
; - 在调用该方法之后添加语句
System.out.println("After setting width");
.
- add the statement
System.out.println("Before setting width");
before the call of that method; - execute the joinpoint twice (i.e., call the method
setWidth
twice), modifying its original parameter fromw
tow + 100
; - 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屋!