Original works, yes, but please mark the source address: www.cnblogs.com/V1haoge/p/9619910.html
In fact, in the previous source code interpretation, the part about weaving is not clear, those front, back, surround, abnormal, such as how the notification is around the target method of execution around?
The most important thing here is recursion, and spring uses a lot of recursive calls to implement this logic, the perfect realization of the weaving logic.
We are uncommon in the Spring Basic series of--AOP practice examples to carry out a logical trace, to explore.
Let's start with the test class:
First we build a method call through the intercept method of the Cglibaopproxy class and execute its proceed method:
Then enter the proceed () method of the Reflectivemethodinvocation class, since the currentinterceptorindex subscript starts with-1, in the + + After the self-increment operation becomes 0, gets the first interceptor in the interceptorsanddynamicmethodmatchers .
Let's look at the contents of the interceptorsanddynamicmethodmatchers :
The first is exposeinvocationinterceptor, this is just before the Spring Basic series-AOP source code Analysis in Source 11, the time to get the notification chain will be placed in the first notification chain, Used to expose method calls to Threadlocal.
Since it is a simple interceptor, the above judgment is not tenable, so the last line is executed directly:
And then into the invoke method of the Exposeinvocationinterceptor method
In this method we can see that the method call Mi is placed in the invocation at 90 lines. What is that invocation? As follows
1 Private Static Final New Namedthreadlocal<> ("Current AOP method invocation");
As you can see, the method call is saved to threadlocal, which is the invocation of the current AOP.
Then execute the Mi.proceed () method, which is a recursive call. Here the proceed method is executed, the next notification will continue, and the execution logic goes back to the proceed () method of the Reflectivemethodinvocation class, when Currentinterceptorindex is 1 after the increment, which points to the next notification in interceptorsanddynamicmethodmatchers :
Obviously, the next notification is a post-afterthrowingtest exception notification.
To execute the Invoke method of this notification, the code is transferred to the invoke method of the Aspectjafterthrowingadvice class.
The proceed method is called directly in the Invoke method of the exception notification, and all remaining calls are executed in full try...catch, and the notification logic is executed in the last catch block.
Except for the normal interceptor, the first notification that is executed is the exception notification, which catches all the remaining invocation logic, that is, any exceptions that occur during this period are caught, and once an exception occurs, execution is interrupted, and the catch logic is executed here.
This goes back to the proceed method of the Reflectivemethodinvocation class. Currentinterceptorindex again from 2, pointing to the third notification in the notification chain:
Back-to-back notification, follow the above logic we look at the next behavior:
In the Afterreturningadviceinterceptor class
Sure enough to perform a post-return notification of the Invoke method go, the first step is still a recursive call, and back to the Reflectivemethodinvocation class of the proceed method to perform the fourth notification:
This is a post-end notification, this notice is a bit special oh, let's take a look at its Invoke method
It is also a direct recursive call, put its logic at the end, this is the real end, directly into the finally block, which indicates what, this means that regardless of whether the next call operation will occur exception, this part of the logic will always be executed.
And now it's back again. The proceed method of the Reflectivemethodinvocation class to perform a fifth notification:
Well, this is a surround notice, this notification is different from other notifications, and other notifications are only executed at the point of the method, but this notification needs to be performed in two ways. So it will have a proceedjoinpoint parameter, which is used to distinguish between the two execution logic: the target method before and after.
Direct execution to the last sentence, the first time to execute the invokeadvicemethod method:
Then execute the Invokeadvicemethodwithgivenargs method:
It wants to directly execute the logic in the notification method, and think about why there is no recursive call but a direct execution of the notification method?
Because surround notifications move recursive calls into the notification logic, custom execution by the programmer, to see my custom wrapping notification logic:
Let's take a look at the general structure, show a piece of logic, and then execute the jp.proceed (OS) method without thinking about the specific logic first. And then another logic. The so-called surround is the logic around the goal before and after execution.
The content of the notification really began to execute, where the front part of the surround notification was first performed.
After we execute the recursive call, we find that logic is running into the Methodinvocationproceedingjoinpoint , what is this class?
This is Proceedjoinpoint implementation class, we do Jp.proceed (OS) method will certainly run here,
In fact, Proceedjoinpoint's proceed method has two overloads, a parameter, a no parameter, respectively, for the target method has parameters and targets without parameters, so here these two methods are logically similar, but the parameter method will be for the parameters of the operation, Set the parameter to the method call, so that the new method parameter will replace the method parameter, which is the principle that we can modify the parameters in the wrapping notification.
The 99th line is to reset the logic of the parameter, the method call has actually saved the parameters: the original parameters.
The 100th line of code is the focus, where a shallow copy of a method call is created, and a shallow copy is used to perform a recursive call to the proceed method.
Why use a light copy? Because we also want to use the same interceptor chain and other object references as the original method call, it's just the independence of the current surround notification (which might be the reason why the surround notification mentioned earlier might invalidate some other notification function)
The logic goes back to the proceed method of the Reflectivemethodinvocation class to perform the sixth notification:
This last notification must be the remaining pre-notification. Let's take a look at its invoke method execution. From:methodbeforeadviceinterceptor
The pre-notification logic for performing notifications here: From:aspectjmethodbeforeadvice
The call ran into the abstractaspectjadvice :
Call again:
Here's the real call to the notification logic: from aspecttest
Then just go back to the Invoke method in the Methodbeforeadviceinterceptor class and proceed to the next step:
This is again a recursive call, which will return the logic back to the proceed method of the Reflectivemethodinvocation class, this time, as all notifications in the notification chain go through once, The rest is the target method. From:cglibaopproxy
So this time the direct implementation of the target method, haha. From:Aspectdemo
Reflection calls the target method.
Executes the target method and then recursively returns to the surround notification aroundtest in the Aspecttest class to perform the back-part logic of the surround notification.
After execution, continue to recursively return to the Aspectjafteradvice class's invoke method to execute the logic in finally:
Execute the Invokeadvicemethod method of the Abstractaspectjadvice class again:
Calling the Invokeadvicemethodwithgivenargs method
The contents of the post-end notification:
Then again, pass the Invoke method back to the Afterreturningadviceinterceptor class:
Call the afterreturning method of the Aspectjafterreturningadvice class:
Here are no longer listed in the Abstractaspectjadvice class of the two methods, direct notification method:
This time back to the Aspectjafterthrowingadvice class of the Invoke method:
The logic in the catch block is not executed here because the entire logic does not have an exception. It then again passes back to the invoke method of the Exposeinvocationinterceptor class to execute the logic in the Finally block:
This statement will empty the method call saved in invocation. The last fallback to the intercept method of the Dynamicadvisedinterceptor class continues with the following logic.
OK, so far, so to speak, here are some additions:
Here is to unify the instructions, so all the announcements are listed, in a call, it is clear that the return value of the part is not correct, I would like to say, try not to use the surround notice and other notifications together, this notification or separate use is better.
What do you think? If you've finished it all, how do you feel?
The realization of weaving is to rely on a sequential notification chain, plus recursive implementation. There is no feeling that the recursion here is very beautiful. Layers of nesting, after the execution of the part to the notification chain, in the recursive chain in the first way to execute the next notification layer in depth, the innermost is the first execution of the notification (pre-notification, the wrapping notice aside), and then layer out, and then the logic of the implementation of the respective notification includes the logic of the target method.
Before I had a doubt is in the Reflectivemethodinvocation class of the proceed method, the first three lines of code, sequential execution of the notification chain, the final execution of the target method, then how to implement the post-notification. After reading the code tracking above, you know it!