Spring framework (6) --- AspectJ implement AOP, --- aspectjaop
AspectJ implement AOP
The Spring framework (4) in the previous article --- explains the foundation of AOP and explains some basic understanding of AOP. Then, this article will really begin to explain the situation of AOP.
The implementation of AOP through AspectJ is much more convenient than the normal implementation of Aop. Therefore, I will not write the fifth article about SpringAOP for the time being, but I will add it after finishing it;
First, let's talk about some things we don't have:
What is Spring's AspectJ AOP?
AspectJ is a cross-section framework that extends the Java language. AspectJ defines the AOP syntax, so it has a dedicated compiler to generate Class files that comply with Java Byte encoding specifications.
Spring and later added support for AspectJ cut-point expressions. @ AspectJ is a new feature of AspectJ1.5. Using the JDK5 annotation technology, you can directly define cut points in Bean classes.
We recommend that you use AspectJ to develop the new Spring framework.
Let's start with a small case, or an example of a previous dog:
1. Import related racks
Import the following four racks based on the original one:
- Spring-aop-4.2.0.RELEASE.jar
- Com.springsource.org. aopalliance-1.0.0.jar
- Spring-aspects-4.2.0.RELEASE.jar
- Com.springsource.org. aspectj. weaver-1.6.8.RELEASE.jar
2. Compile the configuration file applicationContext. xml to import the aop namespace.
<? Xml version = "1.0" encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: p = "http://www.springframework.org/schema/p" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: context = "http://www.springframework.org/schema/context" xsi: schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans. Xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <! -- Bean definitions here --> <! -- Configure the annotation bean package --> <context: annotation-config/> <context: component-scan base-package = "com. study. spring. d_advisor "> </context: component-scan> <! -- Enable automatic proxy --> <aop: aspectj-autoproxy/>
</Beans>
3. Write proxy objects
1 public class Dog {2 3 public void run () {4 System. out. println (""); 5} 6 7 public void jump () {8 9 System. out. println (""); 10 11} 12 13 public void eat () {14 15 System. out. println ("dogs can eat"); 16} 17}
4) write the partition class
Import org. aspectj. lang. annotation. aspect; import org. aspectj. lang. annotation. before; // @ Aspect declares that the current class is a section @ Aspect public class MyAspectJ {// @ Before indicates that the enhanced code @ Before ("execution (* com. study. dog. dog. *(..)) ") public void before1 () {System. out. println ("the breeder asks you to guess ");}}
5. Compile the configuration file
<? Xml version = "1.0" encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: p = "http://www.springframework.org/schema/p" xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: context = "http://www.springframework.org/schema/context" xsi: schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans. Xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <! -- Bean definitions here --> <! -- Configure the annotation bean package --> <context: annotation-config/> <context: component-scan base-package = "com. study. spring. d_advisor "> </context: component-scan> <! -- Enable automatic proxy --> <aop: aspectj-autoproxy/> <! -- Proxy object --> <bean id = "Dog" class = "com. study. dog. Dog"> </bean> <! -- Cut --> <bean id = "MyAspectJ" class = "com. study. dog. MyAspectJ"> </bean> </beans>
6. Compile the test class
1 import org. junit. test; 2 import org. junit. runner. runWith; 3 import org. springframework. beans. factory. annotation. autowired; 4 import org. springframework. beans. factory. annotation. qualifier; 5 import org. springframework. test. context. contextConfiguration; 6 import org. springframework. test. context. junit4.SpringJUnit4ClassRunner; 7 8 // complete configuration file loading 9 @ RunWith (SpringJUnit4ClassRunner. class) 10 @ ContextConfiguration (locations = "classpath: applicationContext. xml ") 11 public class AspectJTest {12 // get dog object 13 @ Autowired14 @ Qualifier (" Dog ") 15 private Dog dog; 16 17 @ Test18 public void Demo1 () {19 dog. eat (); 20 dog. run (); 21 dog. jump (); 22} 23/* 24 * output result: 25 * the breeder asks you to guess 26 * the dog can eat 27 * the breeder asks you to guess 28 * the dog will run 29 * the breeder asks you to guess 30 * the dog will jump 31 */32}
Conclusion: The above is the simplest AspectJ AOP. In this way, you can enter "the breeder asks you to guess what you can do" to exist in multiple methods, it is necessary for future development
Next, let's talk about some very important dry goods!
AspectJ expression:
Syntax: execution (expression)Through the execution function, you can define the cut point method.
Execution (<access modifier>? <Return type> <Method Name> (<parameter>) <exception>)
For example
Execution (public ** (...) matches all public methods
Execution (* cn. study. dao... * (...) matches all class methods in the specified package, excluding sub-packages.
Execution (* cn. study. dao... * (...)... * indicates the package and all classes under the Child package.
Execution (* cn. study. service. UserService. * (..) matches all methods of the specified class
Execution (* cn. study. dao. GenericDAO +. * (..) Matching all class methods of a specific interface
Execution (* save * (...) matches all methods starting with "save ".
AspectJ Enhancement
@ Before: pre-notification, equivalent to BeforeAdvice
@ AfterReturning post-notification, equivalent to AfterReturningAdvice
@ Around surround notification, equivalent to MethodInterceptor
@ AfterThrowing throw a notification, which is equivalent to ThrowAdvice.
@ After final notification. The notification will be executed no matter whether it is abnormal or not.
@ DeclareParents refers to the notification, which is equivalent to IntroductionInterceptor (not required)
Now we can use the above column to fully implement the above dry goods!
Comprehensively enhance the above MyAspectJ:
Import org. aspectj. lang. joinPoint; import org. aspectj. lang. proceedingJoinPoint; import org. aspectj. lang. annotation. after; import org. aspectj. lang. annotation. afterReturning; import org. aspectj. lang. annotation. afterThrowing; import org. aspectj. lang. annotation. around; import org. aspectj. lang. annotation. aspect; import org. aspectj. lang. annotation. before; import org. aspectj. lang. annotation. pointcut; // @ Aspect declares the current Class is a cut surface @ Aspect public class MyAspectJ {// @ Before indicates to execute the enhanced code @ Before ("execution (* com. study. dog. dog. run (..)) ") public void before (JoinPoint joinPoint) {System. out. println ("pre-enhancement .... "+ joinPoint);} // post notification @ AfterReturning (value =" execution (* com. study. dog. dog. jump (..)) ", returning =" returnVal ") public void afterReturin (Object returnVal) {System. out. println ("post enhancement .... return Value of the method: "+ returnVal);} // surround notification @ Aro Und (value = "MyAspectJ. myPointcut () ") public Object around und (ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System. out. println ("enhanced before surround .... "); Object obj = proceedingJoinPoint. proceed (); System. out. println ("enhanced after surround .... "); return obj;} // throw a notification @ AfterThrowing (value =" MyAspectJ. myPointcut () ", throwing =" e ") public void afterThrowing (Throwable e) {System. out. println ("no exception !!! "+ E. getMessage ();} // final notification. The notification will be executed @ After ("MyAspectJ. myPointcut () ") public void after () {System. out. println ("final notification... ");} // cut point definition @ Pointcut (" execution (* com. study. dog. dog. eat (..)) ") private void myPointcut (){}}
Write the test class AspectJTest and the above one remains unchanged
Import org. junit. test; import org. junit. runner. runWith; import org. springframework. beans. factory. annotation. autowired; import org. springframework. beans. factory. annotation. qualifier; import org. springframework. test. context. contextConfiguration; import org. springframework. test. context. junit4.SpringJUnit4ClassRunner; // load the configuration file @ RunWith (SpringJUnit4ClassRunner. class) @ ContextConfiguration (locations = "classpath: applicationContext. xml ") public class AspectJTest {// get the dog object @ Autowired @ Qualifier (" Dog ") private Dog dog; @ Test public void Demo1 () {dog. eat (); dog. run (); dog. jump ();}}
Running result:
Through this example, I believe you have a certain understanding of AspectJ's AOP.
Finally, I will add an interview question:
What is the difference between Advisor and Aspect?
Advisor: traditional aspect of Spring: supports a combination of a cut point and a notification.
Aspect: supports the combination of multiple cut points and multiple notifications.
This article introduces some shortcomings. Thank you!