The times may come? Aspect-oriented programming, what is the AspectJ language was summarized and described about pointcuts, but there were more pointcuts than I expected. It's long and difficult to understand, and there seems to be pointcuts implemented in AspectJ, so I decided to divide it. Please note that it was divided into dogmatism and prejudice.
Static initialization is provided for pointcuts related to static initializers Represents the "time" when a static initializer that takes a type pattern as an argument and initializes a static field in a class is called and executed.
Sample.java
//Write the class name directly or use wildcards
staticinitialization(Session+)
Also known as a static initializer or class initializer. A special method declared for each class to initialize the value of a static field
staticInitializer.java
static {
//Code that initializes the value of a static field
}
Pointcuts can be combined using operators However, be careful, as the call seems to wrap the execution as shown in the above figure, so call && exectuion and Even if it looks like the code below, it's actually different
Sample.java
class Sample {
Sample() {
Main.init()
}
}
class Main {
static void init() {
hoge();
}
static int length() {
return hoge
}
}
As shown in the figure below, execution specifies the light blue part (the part outside the join point), and call is in the green part. && condition never becomes True
But what if you want to create such a condition? In addition to selecting a specific type of join point for the solution, we also offer a primitive pointcut that selects the join point based on the location in the program.
: black_small_square: ** within (type pattern) ** Select all join points that occur in class or interface declarations that match the type pattern Any type of join point
: black_small_square: ** withincode (method pattern) ** or ** withincode (constructor pattern) ** Select all join points that occur in the body of the method or constructor that match the argument pattern Any type of join point
By using the above, you can specify that it is in a specific class or method.
There are two pointcuts related to business flow, ** cflow ** and ** cflow below **. Take a pointcut as an argument to represent "time"
Sample.java
cflow(call(void Main.init()))
:black_small_square:cflow Selects all join points that occur between the start and end of the join point P selected by the argument pointcut. cflow selects the join point P selected by the argument pointcut
:black_small_square:cflowbelow It is almost the same as cflow, but unlike cflow, the join point P selected by the pointcut of the argument is not selected.
withincode
withincode.java
call(void Main.hogeB()) && withincode(void Main.init())
Since withincode is a join point that occurs in the body of the method that matches the argument pattern In this case, only the join point where the method called main.hogeA is called So there is no match for call (void Main.hogeB ())
cflow
cflow.java
call(void Main.hogeB()) && cflow(call(void Main.init()))
Since cflow selects all the join points that occur between the start and end of the join point P selected by the argument pointcut. In this case, the join point where the methods main.hogeA and main.hogeB are called Therefore, there is something that matches call (void Main.hogeB ()).
The call pointcut selects the "when" when the method specified in the method pattern is called as the join point. This join point is not only for methods, but also for method calls that appear in the aspect definition. This also applies to pointcuts other than call.
Hello.java
impoort java.io.*;
aspect Tracer {
pointcut tracedMethods(): call(* PrintStream.println(..));
before(): tracedMethods() {
System.out.println("** method call");
}
}
public class Hello {
public static void say() {
System.out.println("Hello");
}
public static void main(String[] args) {
say();
}
}
Writing a program like the one above would result in an infinite loop
To avoid this problem, there is ** advice execution ** in the advice related pointcut Represents the "time" when the body of any advice is being executed without taking any arguments
Sample.java
!cflow(adviceexecution())
//Select all join points except while running the body of advice
There are three pointcuts related to program execution context information: ** this **, ** target **, and ** args **.
:black_small_square:this Select all join points that occur in the body of a method or constructor running by an instance of a type (including subclasses and subinterfaces) that matches the pointcut arguments Any type of join point
:black_small_square:target Select all method calls and field access for instances of types (including subclasses and subinterfaces) that match the pointcut arguments as join points. Any type of join point
:black_small_square:args Select a method or constructor call that takes an argument of the type that matches the pointcut argument as the join point.
Select a join point when the class of the object pointed to by this variable matches the pointcut argument
Sample.java
call(* *(..)) && this(Session)
//The above selects the call of any method from the methods of the Session class or its subclass as a join point.
Select a join point when it matches the class type and pointcut arguments of the object being targeted for method invocation or field access
Sample.java
class Session {}
class BookSession extends Session{}
Sample.java
call(* Session.*(..)) && target(BookSession)
//The above selects only when calling the method declared in the Session class as the join point when calling on the BookSession object.
Session s = new BookSession(301);
s.doIt();
Sample.java
call(* *(..)) && args(BookSession, ..)
//Select a method call as the join point whose first argument is an instance of the BookSession class
Note that the args pointcut also uses the actual type of the argument object when looking up the type.
Recommended Posts