I. Overview of SPRINGAOP
1. AOP Concept
AOP is the abbreviation for aspect-oriented programming (plane-oriented programming). Wikipedia explains the following:
Aspect is a new modular mechanism for describing crosscutting concerns (crosscutting concern) scattered across objects, classes, or functions. The separation of the crosscutting concerns from the point of concern is the core of the program design oriented to the aspect. Separation of concerns enables code that solves a particular domain problem to be independent of the business logic code, where the code of the business logic no longer contains calls to specific code for the picking problem, and the relationship between business logic and a particular domain problem is encapsulated and maintained by facets, so that changes that are scattered throughout the application can be managed well.
2, advice notice
The advice definition provides a weaving interface for aspect enhancement at the connection point. In spring AOP, he mainly describes the tangent behavior that spring AOP injects around method invocations. Advice is the interface defined in Org.aopalliance.aop.Advice. This unified interface is used in spring AOP, and this interface provides additional details and extensions for AOP aspect-enhanced weaving capabilities, such as providing a more specific type of notification, such as Beforeadvice,afteradvice,throwsadvice.
2.1 Beforeadvice
First we start with the Beforeadvice:
In the inheritance relationship of Beforeadvice, the pre-enhanced interface Methodbeforeadvice for the target method to be enhanced is defined, and a callback function is implemented using this predecessor interface:
void before(Method method,Object[] args,Object target) throws Throwable;
As a callback function, the implementation of the Before method is configured in advice to the target method and is called back when the target method is invoked. The specific parameters are: Method object, which is the reflection object of the target method; An array of object[] objects containing the input parameters of the target method. Taking Countingbeforeadvice as an example to illustrate the specific use of Beforeadvice, Countbeforeadvice is the implementation of the interface Methodbeforeadvice, he just counted the number of times the method was called, as a facet enhancement implementation , he will make statistics based on the method name of the calling method, and put the statistical results into a map based on the method name and the number of calls as key-value pairs. The code is as follows:
Public class countingbeforeadvice extends methodcounter implements Methodbeforeadvice { //Implement method of Methodbeforeadvice interface with pre-notification Public void before(Method m, object[] args, Object target)throwsThrowable {//using the target object method as a parameter, call the Count method of the parent class Methodcounter to count the number of method callsCount (m); The source code of}}countingbeforeadvice's parent methodcounter is as follows: Public class methodcounter implements Serializable { Map Collection of method calls, method name, number of calls to the stored method Privatehashmap<string, integer> map =NewHashmap<string, integer> ();//Total number of calls for all methods Private intAllcount;//Statistics method call number, Countingbeforeadvice call entry protected void Count(Method m) {count (M.getname ()); }//Statistics The number of calls to the specified name method protected void Count(String methodName) {//Gets the number of invocations of the specified name method from the collection of method invocation number , method nameInteger i = Map.get (methodName);//If the number of calls is not NULL, the number of calls is added to 1, and if the number of calls is NULL, the number of calls is set to 1i = (i! =NULL) ?NewInteger (I.intvalue () +1) :NewInteger (1);//Reset the number of method calls saved in the collectionMap.put (MethodName, i);//Total number of calls to all methods plus 1++allcount; }//Gets the number of calls to the specified name method Public int Getcalls(String methodName) {Integer i = map.get (methodName);return(I! =NULL? I.intvalue ():0); }//Gets the total number of calls for all methods Public int Getcalls() {returnAllcount; } Public Boolean equals(Object Other) {return(Other! =NULL&& Other.getclass () = = This. GetClass ()); } Public int hashcode() {returnGetClass (). Hashcode (); }}
2.2 Afteradvice
In the advice implementation system, Spring also provides afteradvice this type of notification, here the implementation of Afterreturningadvice notification as an example, the code is as follows:
publicinterface AfterReturningAdvice extends AfterAdvice {//后置通知的回调方法,在目标方法对象调用结束并成功返回之后调用// returnValue参数为目标方法对象的返回值,method参数为目标方法对象,args为 //目标方法对象的输入参数 voidthrows Throwable;}
The Afterreturning method is also a callback function, the AOP application needs to provide the aspect enhancement in this interface implementation the concrete design, after this advice notification is configured correctly, when the target method call ends and returns successfully, the interface is called by SPRINGAOP. As in the previous analysis, in the Spring AOP package, you can see the Countingafterreturningadvice, which is basically the same:
public class countingafterreturningadvice extends methodcounter implements afterreturningadvice { //implement callback method for post-notification afterreturningadvice public
void afterreturning (Object o, Method m, Object[] args, Object target) throws throwable {//call Parent The count method of the class Methodcounter, the number of calls to the statistics method count (m); }}
In the interface method afterreturning that implements Afterreturningadvice, you can call the Count method of Methodcounter to complete the count of the number of target method calls based on the method name.
2.3 Throwsadvice
Let's take a look at another type of advice notification Throwsadvice. For Throwsadvice, there is no interface method that needs to be implemented, he is called back when throwing an exception, and this callback is done using the reflection mechanism of AOP. You can use Countingthrowsadvice to understand how throwsadvice is used:
Public Static class countingthrowsadvice extends methodcounter implements Throwsadvice { //When throwing an IO-type exception, the number of times the exception is called is counted Public void afterthrowing(IOException ex)throwsThrowable {count (IOException.class.getName ()); }//When throwing a callback method with an Uncheckedexception type exception, count the number of times the exception was called Public void afterthrowing(Uncheckedexception ex)throwsThrowable {count (UncheckedException.class.getName ()); } }
3. Pointcut Tangent Point
Determines which connection point the advice notification should act on, that is, by pointcut to define a collection of methods that need to be enhanced, the selection of these collections can be done in accordance with certain rules. Pointcut often means identifying methods, for example, where these need to be enhanced can be identified by a regular expression, or matched according to a method name. The source code is as follows:
publicinterface Pointcut { //获取类过滤器 ClassFilter getClassFilter(); //获取匹配切入点的方法 MethodMatcher getMethodMatcher(); //总匹配的标准切入点实例
Looking at the inheritance system of Pointcut pointcuts, it is found that the implementation classes of Pointcut pointcuts are very many, such as annotationmatchingpointcut for annotation configuration, jdkregexpmethodpointcut for regular expressions, etc. We take jdkregexpmethodpointcut as an example to analyze the specific implementation of pointcut matching, the source code is as follows:
Public class jdkregexpmethodpointcut extends abstractregexpmethodpointcut { //Regular expression pattern to compile Privatepattern[] Compiledpatterns =Newpattern[0];//compile-time regular expression pattern to exclude Privatepattern[] Compiledexclusionpatterns =Newpattern[0];//Initializes the given pattern string array to the compiled regular expression pattern protected void initpatternrepresentation(string[] patterns)throwspatternsyntaxexception { This. Compiledpatterns = Compilepatterns (patterns); }//Initializes the given pattern string array to the regular expression pattern to be excluded at compile-time protected void initexcludedpatternrepresentation(string[] excludedpatterns)throwspatternsyntaxexception { This. Compiledexclusionpatterns = Compilepatterns (excludedpatterns); }//Use regular expression to match given name protected Boolean matches(String pattern,intPatternindex) {Matcher Matcher = This. Compiledpatterns[patternindex].matcher (pattern);returnMatcher.matches (); }//Use the regular expression you want to exclude to match the given name protected Boolean matchesexclusion(String candidate,intPatternindex) {Matcher Matcher = This. Compiledexclusionpatterns[patternindex].matcher (candidate);returnMatcher.matches (); }//compiles the given string array into a regular expression pattern PrivatePattern[]Compilepatterns(string[] source)throwspatternsyntaxexception {pattern[] destination =NewPattern[source.length]; for(inti =0; i < source.length; i++) {Destination[i] = Pattern.compile (Source[i]); }returnDestination }}
4. Advisor notification Device
After completing the Aspect enhancement Design (Advice) and the design of the focus (Pointcut) for the target method, you need an object to combine them, and the advisor is the way to do it. Through he can define which notification should be used and at which point of interest to use it. There are two properties in defaultpointcutadvisor, namely advice and pointcut. These two properties allow you to configure advice and pointcut, respectively. The source code is as follows:
Public class defaultpointcutadvisor extends abstractgenericpointcutadvisor Implements Serializable { //default Pointcut //pointcut.true is defined in the Pointcut as: Pointcut TRUE = truepointcut.instance; PrivatePointcut Pointcut = pointcut.true;//No parameter construction method, create an empty notifier Public Defaultpointcutadvisor() { }//Create a notifier that matches all methods Public Defaultpointcutadvisor(Advice Advice) { This(pointcut.true, advice); }//Create a notifier that specifies pointcuts and notifications Public Defaultpointcutadvisor(Pointcut Pointcut, Advice Advice) { This. pointcut = Pointcut; Setadvice (advice); }//Set pointcuts for notifications Public void Setpointcut(Pointcut Pointcut) { This. Pointcut = (pointcut! =NULL? Pointcut:Pointcut.TRUE); }//Get pointcuts PublicPointcutGetpointcut() {return This. pointcut; } PublicStringtoString() {returnGetClass (). GetName () +": pointcut ["+ getpointcut () +"]; Advice ["+ getadvice () +"]"; }}
In the above source, the default entry point of the notifier is pointcut.true,pointcut.true in the pointcut is defined as: Pointcut TRUE = truepointcut.instance
The instance of Truepointcut is a single piece, such as using the static class variable to hold a single instance, using the private proprietary constructor to ensure that a single piece is not created and instantiated again except in the current single implementation.
The implementation of Truepointcut and Truemethodmatcher is as follows:
/** * Canonical Pointcut instance that always matches. * * @author Rod Johnson * *@SuppressWarnings("Serial") class Truepointcut implements Pointcut, Serializable { Public Static FinalTruepointcut INSTANCE =NewTruepointcut ();/** * Enforce Singleton pattern. * Here is the implementation of the single-piece mode, set the private constructor, so that it can not be directly instantiated * and set a static class variable to ensure that the instance is unique * / Private Truepointcut() { } PublicClassfilterGetclassfilter() {returnClassfilter.true; } PublicMethodmatcherGetmethodmatcher() {returnMethodmatcher.true; }/** * Required to support serialization. Replaces with canonical * instance on deserialization, protecting Singleton pattern. * Alternative to overriding {@code equals ()}. */ PrivateObjectReadresolve() {returnINSTANCE; }@Override PublicStringtoString() {return "Pointcut.true"; }}
/** * Canonical Methodmatcher instance that matches all methods. * * @author Rod Johnson * *@SuppressWarnings("Serial") class Truemethodmatcher implements Methodmatcher, Serializable { Public Static FinalTruemethodmatcher INSTANCE =NewTruemethodmatcher ();/** * Enforce Singleton pattern. */ Private Truemethodmatcher() { } Public Boolean Isruntime() {return false; } Public Boolean matches(method, Class Targetclass) {return true; } Public Boolean matches(method, Class Targetclass, object[] args) {//Should never be invoked as Isruntime returns false. Throw NewUnsupportedoperationexception (); }/** * Required to support serialization. Replaces with canonical * instance on deserialization, protecting Singleton pattern. * Alternative to overriding {@code equals ()}. */ PrivateObjectReadresolve() {returnINSTANCE; }@Override PublicStringtoString() {return "Methodmatcher.true"; }}
Next we begin to learn what spring AOP is all about
To be Continued ...
Spring Technology Insider: The implementation principle of Spring AOP (I.)