In fact, the biggest tragedy is that you know what you want, but don’t know how to insist! In fact, the recent obsession with Deadpool and my usual state is almost the same, with a mixed mentality to do anything, often the probability of success will be greater!!

A picture town building!!

I talked about AspectJ’s integration issues, so if you haven’t read the previous article, check out the first article in this series.

AOP buried point from entry to abandonment (I)

This article fully covers AspectJ integration issues, so let’s talk about how best to use AspectJ to my advantage…

1. An explanation of some nonsense

In fact, I think this is the hardest thing to say, because there are so many concepts to remember! In fact, memory is my most annoying thing, but I am an ape, a great ape! So when it comes to reciting the text…

Let’s start with a piece of code

@Aspect
public class TraceAspect {
    private static final String TAG = "hjl";

    @Before("execution(* android.app.Activity.on*(..) )")
    public void onActivityMethodBefore(JoinPoint joinPoint) {
        String key = joinPoint.getSignature().toString();
        Log.e(TAG, "OnActivityMethodBefore: Facets of the point executed!"+ key); }}Copy the code

So what does this code do? E (TAG, “onActivityMethodBefore: Cut point executed! “). + key); * * code! Let’s go through them one by one!

1.1 Meaning of top@ Aspect

The @aspect annotation is the basis for everything below. Without this annotation AspectJ would not have the corresponding entry and would not have the corresponding Aspect! AspectJ will find all the @Aspect annotations and then

1.2 Concepts of Wildcards (Pointcut Syntax)(Difficult points)

First, the general format of wildcards :(I don’t know if I understand them correctly, but I didn’t find anything wrong when I used them in the project)

@ annotations Access permissions Return value type The name of the class The function name parameter

In general, wildcards are in this format. Let’s use one of the above wildcards to illustrate:

execution(* android.app.Activity.on*(..) )Copy the code

Android.app.activity.on * specifies the full path of the function name. The function name is android.app.activity.on *. The one at the back stands for ON, and the one at the back (..) Indicates that the parameter can be any value.

That’s what a wildcard means! In fact, when LEARNING AspectJ, I found the most difficult to understand the corresponding operator, if you understand the operator, really easy! But if you had done the backend before, this should have been easy, and AOP in the Spring framework is the same as Pointcut syntax. Because they are not Java background developers, so the explanation may not be in place, you can go to your Java background group to ask, learn about it! It should be much better than what I said, because I’m really new to this stuff!

Because usually have no contact, so here write some commonly used bar!

classification

JPoint instructions Pointcut syntax description
method execution Typically specifies the execution of a method execution(MethodSignnature)
method call Function called call(MethodSignnature)
constructor call The constructor is called call(ConstructorSignature)
constructor execution The constructor executes internally execution(ConstructorSignature)
field get Read the variable get(FieldSIgnature)
field set Write variables set(FieldSIgnature)
handler Exception handling Handler (TypeSignature) Note: This command is used only with @before (), but not with @after or @around
advice execution Advice to perform adciceexectuin()

People like the reference

Sigbature Syntax (one space apart)
MethodSignature @annotation access return value type class name. Function name (parameter)
ConstructorSignature @annotation access class name. New (parameter)
FieldSignature @annotation access variable type class name. Class member variable name

Signature syntax details

Sigbature Specifies the syntax explain
@ annotations @ Full class name, if not written
Access permissions Public /private/portect and static/finalPay attention toIf you write “public” only, all matches will be matched. If you write “public”, all matches will be matched
Return value type If the type is not qualified, the wildcard character * is used
Class name function name Wildcards that can be used, including * and.. Plus sign. Where * is used for accompany divide. Any character other than the sign, and.. Represents any word package, and the + sign represents a subclassPay attention toConstructorSignature (); ConstructorSignature (); The function name can be left blank), reused and used with annotations. At the beginning
Variable types Member variable type, * for any type
Class name. Member variable name Class names can use wildcards, and functions. The function name is similar

Advice content

Advice instructions
@Before(Pointcut) Execute before jPoint
@After(Pointcut) Execute after jPoint
@Around(Pointcut) Replace the original code, if you want to perform the original code, need to use proceedingJoinPoint. Proceed ();Pay attention to: Do not use with @after, @before, etc

Above this write table of you first simple look, estimate you still can come back to see for a while!!

1.2.1 method->call example:

    @Pointcut("call(* com.jinlong.aspectjdemo.MainActivity.callMethod(..) )")
    public void callMethod() {// To demonstrate the use of the call method} @before ("callMethod()")
    public void beforeCallMethod(JoinPoint joinPoint) {
        Log.e(TAG, "Demonstration of call method");
    }
Copy the code

The @pointcut is used to annotate a method, the call is followed by a series of wildcards, which are simply the address of a method. * means that no value is returned, and @before means that the method is executed Before slicing! Here don’t com. Jinlong. Aspectjdemo. MainActivity. CallMethod this address is wrong!

In fact, this code can be simplified to

    @Before("call(* com.jinlong.aspectjdemo.MainActivity.callMethod(..) )")
    public void beforeCallMethod(JoinPoint joinPoint){
        Log.e(TAG, "Demonstration of call method");
    }
Copy the code

If you replace @before with @after, it will print After the method!!

Here’s another piece of code:

    @Around("call(* com.jinlong.aspectjdemo.MainActivity.callMethod(..) )")
    public void aroundCallMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        Log.e(TAG, "Method execution time is + (endTime - startTime));
    }
Copy the code

This code is to count the execution time of the method, and here we focus on two things

  • joinPoint.proceed(); Restore your original code, without this sentence, your original code is gone! Didn’t!
  • @around replace the original code, plus the above sentence can restore the previous code!

So here you can calculate the execution time of the method!! That’s @around!

1.2.2 method-> Execution:

In the past, I thought execution and call were the same, but later I came to know that the biggest difference is this!!

Let’s say you have a method called callMethod(), right? Then use call to drip like this

The corresponding method of call (); callMethod();Copy the code

But that’s what programming looks like if it’s execution

callMethod(){the corresponding method of execution (); }Copy the code

There is no difference in the others, and I will not illustrate them here.

1.2.3 Operation of construction method

First, this thing is used on the constructor, that is, for the corresponding constructor for the corresponding section operation! But I have only one question do not understand, if I according to the above method of wildcard operation, according to the common sense should also be able to operate in the corresponding section of ah! Compilation does not report errors, but is how also print out the result, also please understand the god to help me answer it!

There is also a solution to the corresponding constructor problem following the table above

    @Before("execution(com.jinlong.aspectjdemo.Person.new(..) )") public void beforeConstructorExecution (JoinPoint JoinPoint) {/ / this is according to the Constructor of the e (the TAG,"before->" + joinPoint.getThis().toString() + "#" + joinPoint.getSignature().getName());
    }
Copy the code

I’ve tried this code, and I can print it out. ** constructorSignature@ annotation access class name. New (parameter)** this way you can print the corresponding result! But I urge you to replace @before with @after or your print might be empty!

1.2.4 Questions about corresponding member variables

That is, you can modify the class member variables, no matter how you set the final return is you set the value!

Take a look at this code:

Here is a normal class:

public class Person {
    private String name;
    private String age;

    public Person() {
    }

    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) { this.age = age; }}Copy the code

That’s the core code!

    @Around("get(String com.jinlong.aspectjdemo.Person.age)") public String aroundFieldGet(ProceedingJoinPoint joinPoint) throws Throwable {// Execute the original code Object obj = joinPoint.proceed(); String age = obj.toString(); Log.e(TAG,"age: " + age);
        return "100";
    }
Copy the code

The name of the fieldSignature@ annotation access variable type is used here. If you override the toString() method, obj returns a null object. If you override the toString() method, obj returns a null object. I really do not know why, but also please understand to inform one or two! “Get” is a key word. There are no access permissions or annotations, so we omit the full path of the returned variable type (String) and the class member variable name.

Take a look at the following code:

    @Around("set(String com.jinlong.aspectjdemo.Person.age)")
    public void aroundFieleSet(ProceedingJoinPoint joinPoint) {
        Log.e(TAG, "aroundFieleSet: " + joinPoint.getTarget().toString() +
                joinPoint.getSignature().getName());
    }
Copy the code

This method can be set to the corresponding age property, which is modified whenever an assignment occurs! To clarify, this code does not **joinPoint.proceed(); ** code, so the previous code to execute the content will be invalidated! That is to say, it was replaced by the printed paragraph! In fact when you run this code up here you’ll notice one thing, the Log is printed twice. Why? Do you want to! this.age = age; Occurs once in the set method, and once in the constructor. So let’s take a look at that. So I’m going to exclude constructors and what do I do about that total time? We’re going to use withinCode!

1.2.5 WithinCode excludes content

How do you understand this thing? Represents a JPoint involved in a constructor or function. Don’t understand! It doesn’t matter, look at a piece of code you will understand!

    @Around("set(String com.jinlong.aspectjdemo.Person.age)&&! withincode(com.jinlong.aspectjdemo.Person.new(..) )") public void aroundFieleSet(ProceedingJoinPoint joinPoint) throws Throwable {// Set the corresponding member variable joinPoint.proceed(); }Copy the code

1.2.4 states that a set will be in both places, but I don’t want that constructor. How can I exclude it? Behind it is to add the code * *. Com jinlong. Aspectjdemo. Person. The new (..) )** is to exclude the contents of the constructor! In fact, it is easy to understand, excluding the corresponding constructor, it is easy to understand that withincode is carrying something, but because of the inverse, so it is not carrying this thing!! That’s it…

1.2.5 Catching Exceptions of the Handler

This is a bit simpler by comparison, directly on the code:

This is an exception in the code, a very simple exception, if the method goes to the corresponding catch, then it can catch the corresponding exception!

    private void catchMethod() { try { int sum = 100 / 0; } catch (Exception e) { e.printStackTrace(); }}Copy the code

Here comes the key code…

    @Before("handler(java.lang.Exception)")
    public void handlerMethod() {
        Log.e(TAG, "HandlerMethod: Exception generated");
    }
Copy the code

It is easy to use a handler keyword and add an exception to the full path, ok, but note that the first comment can only be @Before, remember!!

1.2.6 Use of annotations

There are many third parties you don’t know the name of, but what if you still want to use them? That’s annotations, because annotations are a great way to address this need.

Here’s another piece of code:

Define a comment:

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DebugTrace {
}
Copy the code

Since these notes are not the focus of this article, they will not be covered here. If you are interested, you can search. This annotation is mainly used after compiling, and it is used for methods and member variables.

In addition to the following code can carry out the corresponding section of the operation!

    @Pointcut("execution(@com.jinlong.aspectjdemo.DebugTrace * *(..) )")
    public void DebugTraceMethod() {
    }

    @Before("DebugTraceMethod()")
    public void beforeDebugTraceMethod(JoinPoint joinPoint) {
        String key = joinPoint.getSignature().toString();
        Log.e(TAG, "Note this method executes:");
    }
Copy the code

You should be familiar with this code, which is to add the corresponding section operation to the method content. Finally, add a corresponding annotation to the method you use. It’s that simple!

    @DebugTrace
    private void mothod1() {
        Log.e(TAG, "Method 1 is executed.");
    }
Copy the code

The above basically contains some content that can be used in the application of our APP. Please point out if there is anything that is not in place. Because this is the first time to contact this thing, maybe some details are not in place, please understand!!

Want to see the source code? Want to see the link? Click here