1. Overview
What is aspect-oriented programming?
Aspect-oriented programming is a programming paradigm (other common programming paradigms include process-oriented programming, object-oriented programming OOP, function-oriented programming, event-driven programming and Aspect-Oriented programming). It is not a programming language. Aspect-oriented programming can solve specific problems, but it can not solve them. All problems, it is a complement to object-oriented programming, not a substitute.
It can solve the problem of code repeatability to a large extent, and can achieve separation of concerns, such as functional requirements and non-functional requirements, so as to achieve centralized management, enhance the readability and maintainability of the code.
2. Common usage scenarios of AOP
Common usage scenarios in system development are
Permission control
Cache control
Transaction control
Audit logs
Performance monitoring
Distributed Tracking
Exception handling
3. Two main concerns of Spring AOP
Pointcut express
Aspect expression mainly expresses how to find the logical point of the insertion of the aspect. Point cut expression provides a wealth of expressions to allow us to insert the aspect.
Five Advice s
After finding the entry point, there are five main ways to specify when to implant code, as follows:
@Before Before advice
@ After(finally), post-notification, after the method has been executed
@ AfterReturning, return notification, after return value
@ AfterThrowing, exception notification, after throwing an exception
@Around Around notification, surround notification contains all of the above types
The above two concerns conclude with a statement about where and when to do our code entry.
4. Common Section Expressions
1. within expression, matching methods under packages or classes
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * //Matching all methods in the ProductService class * @Pointcut("within(com.ruoli.service.ProductService)") * //Method of matching all classes under com.ruoli package and subpackage * @Pointcut("within(com.ruoli..*)") */ @Aspect @Component public class PkgTypeAspectConfig { @Pointcut("within(com.ruoli.service.sub.*)") public void matchType(){} @Before("matchType()") public void before(){ System.out.println(""); System.out.println("###before"); } }
2. Object Matching
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * //A method that matches the target object of an AOP object to a specified type, that is, an AOP proxy object of LogService * @Pointcut("this(com.ruoli.log.Loggable)") * //Method of matching the target object (not the object after aop proxy) that implements the Loggable interface * @Pointcut("target(com.ruoli.log.Loggable)") * //this DeclareParents(Introduction) can be intercepted * //target Do not intercept Declare Parents (Introduction) * //Method matching in all bean s ending with Service * @Pointcut("bean(*Service)") * Created by cat on 2016-12-04. */ @Aspect @Component public class ObjectAspectConfig { @Pointcut("bean(logService)") public void matchCondition(){} @Before("matchCondition()") public void before(){ System.out.println(""); System.out.println("###before"); } }
3. Method of parameter matching and configuration of specified parameters
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * //Matching any method that starts with find and has only one Long parameter * @Pointcut("execution(* *..find*(Long))") * //Match any method that starts with find and the first parameter is Long * @Pointcut("execution(* *..find*(Long,..))") * //Matching any method with only one Long parameter * @Pointcut("within(com.ruoli..*) && args(Long)") * //A Method of Matching the First Parameter of Long Type * @Pointcut("within(com.ruoli..*) && args(Long,..)") * Created by cat on 2016-12-04. */ @Aspect @Component public class ArgsAspectConfig { @Pointcut("args(Long,String) && within(com.ruoli.service.*)") public void matchArgs(){} @Before("matchArgs()") public void before(){ System.out.println(""); System.out.println("###before"); } }
4. Annotation Matching
There are mainly method-level annotations, class-level annotations and parameter-level annotations.
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * //Matching method annotated with AdminOnly annotations * @Pointcut("@annotation(com.ruoli.anno.AdminOnly) && within(com.ruoli..*)") * //Match the method // class level underneath the class marked with NeedSecured * @Pointcut("@within(com.ruoli.anno.NeedSecured) && within(com.ruoli..*)") * //Method //runtime level matching classes with NeedSecured and their subclasses * In the context of spring context, there is no difference between the two. * @Pointcut("@target(com.ruoli.anno.NeedSecured) && within(com.ruoli..*)") * //Method of matching incoming parameter classes with Repository annotations * @Pointcut("@args(com.ruoli.anno.NeedSecured) && within(com.ruoli..*)") * Created by cat on 2016-12-04. */ @Aspect @Component public class AnnoAspectConfig { @Pointcut("@args(com.ruoli.anno.NeedSecured) && within(com.ruoli..*)") public void matchAnno(){} @Before("matchAnno()") public void before(){ System.out.println(""); System.out.println("###before"); } }
5. execution expression
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * //Match any common method @Pointcut("execution(public * com.ruoli.service.*.*(..))") //Matching the non-parametric methods in Service classes under com.imooc packages and subpackages @Pointcut("execution(* com.ruoli..*Service.*())") //Method of matching any Service class with only one parameter under com.imooc package and subpackage @Pointcut("execution(* com.ruoli..*Service.*(*))") //Any method of matching any class under com.imooc package and subpackage @Pointcut("execution(* com.ruoli..*.*(..))") //Any method that matches the return value of String under com.imooc package and subpackage @Pointcut("execution(String com.ruoli..*.*(..))") //Matching exception execution(public * com.ruoli.service.*.*(..) throws java.lang.IllegalAccessException) * */ @Aspect @Component public class ExecutionAspectConfig { @Pointcut("execution(public * com.ruoli.service..*Service.*(..) throws java.lang.IllegalAccessException)") public void matchCondition(){} @Before("matchCondition()") public void before(){ System.out.println(""); System.out.println("###before"); } }
5. Five examples of notification code
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.omg.CORBA.Object; import org.springframework.stereotype.Component; /** * @Before("matchAnno()") * @After("matchAnno())") //Equivalent to final * @AfterReturning("matchException()") * @AfterThrowing("matchException()") * @Around("matchException()") * @Before(value = "matchLongArg() && args(productId)") * public void beforeWithArgs(Long productId) * @AfterReturning(value = "matchReturn()",returning = "returnValue") * public void getReulst(Object returnValue) * */ @Aspect @Component public class AdviceAspectConfig { /******pointcut********/ @Pointcut("@annotation(com.ruoli.anno.AdminOnly) && within(com.ruoli..*)") public void matchAnno(){} @Pointcut("execution(* *..find*(Long)) && within(com.ruoli..*) ") public void matchLongArg(){} @Pointcut("execution(public * com.ruoli.service..*Service.*(..) throws java.lang.IllegalAccessException) && within(com.ruoli..*)") public void matchException(){} @Pointcut("execution(String com.ruoli..*.*(..)) && within(com.ruoli..*)") public void matchReturn(){} /******advice********/ @Before("matchLongArg() && args(productId)") public void before(Long productId){ System.out.println("###before,get args:"+productId); } @Around("matchException()") public java.lang.Object after(ProceedingJoinPoint joinPoint){ System.out.println("###before"); java.lang.Object result = null; try{ result = joinPoint.proceed(joinPoint.getArgs()); System.out.println("###after returning"); }catch (Throwable e){ System.out.println("###ex"); //throw e.printStackTrace(); }finally { System.out.println("###finally"); } return result; } }