Очень неформально совет around
перехватывает заданную точку соединения и может внедрять новое поведение до, после и вместо этой точки соединения. proceed
— это специальная функция, которая позволяет around
совету продолжать выполнение joinpoint
.
Из типов советов, поддерживаемых AspectJ (т. е. before
, after
и around
), совет 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
. И воля:
System.out.println("Before setting width");
перед вызовом этого метода;setWidth
), изменив исходный параметр с w
на w + 100
;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)
оператором 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
, не означает, что вы должны повторить то же самое, что было сделано в этом примере, и не точно показывает, как происходит процесс плетения под капотом.