This article introduces the method of using AOP in SpringBoot project. I will share it with you. The details are as follows:
1. Overview
Using general logic to implement AOP technology can greatly simplify the writing of programs, such as signature verification, authentication, etc. Spring's declarative transactions are also implemented through AOP technology.
For specific code, please refer to the example project https://github.com/qihaiyan/springcamp/tree/master/spring-aop
Spring's AOP technology has four core concepts:
Pointcut: point cut, used to define which method will be intercepted, for example execution(* cn.springcamp.springaop.service.*.*(..))
Advice: The action to be executed after intercepting the method
Aspect: Slice, combine Pointcut and Advice together to form a cut surface
Join Point: An instance of Pointcut during execution
Weaver: A framework for implementing AOP, such as AspectJ or Spring AOP
2. Definition point definition
Commonly used Pointcut definitions include execution and @annotation. execution defines a method-free and is used to implement a relatively common section. @annotation can be added as annotation to specific methods, such as Spring's Transaction annotation.
The execution point-cut definition should be placed in a public class to centrally manage the point-cut definition.
Example:
public class CommonJoinPointConfig { @Pointcut("execution(* cn.springcamp.springaop.service.*.*(..))") public void serviceLayerExecution() {}}In this way, in the specific Aspect class, you can refer to the tangent point through CommonJoinPointConfig.serviceLayerExecution().
public class BeforeAspect { @Before("CommonJoinPointConfig.serviceLayerExecution()") public void before(JoinPoint joinPoint) { System.out.println(" ---------------> Before Aspect "); System.out.println(" -----------------> before execution of " + joinPoint); }}When the tangent point needs to be changed, you only need to modify the CommonJoinPointConfig class, without modifying each Aspect class.
3. Commonly used face cutting
Before: Execute Advice before the method is executed, which is often used for signature verification, authentication, etc.
After: Execute after the method execution is completed, whether the execution is successful or the exception is thrown.
AfterReturning: Execute only after the method execution is successful.
AfterThrowing: Execute only after a method execution throws an exception.
A simple Aspect:
@Aspect@Componentpublic class BeforeAspect { @Before("CommonJoinPointConfig.serviceLayerExecution()") public void before(JoinPoint joinPoint) { System.out.println(" ---------------> Before Aspect "); System.out.println(" ----------------> before execution of " + joinPoint); }}4. Custom annotations
Suppose we want to collect the execution time of a specific method, a more reasonable way is to customize an annotation and then add this annotation to the method that needs to collect the execution time.
First define an annotation TrackTime:
@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface TrackTime { String param() default "";}Then define an Aspect class to implement the behavior of annotation:
@Aspect@Componentpublic class TrackTimeAspect { @Around("@annotation(trackTime)") public Object around(ProceedingJoinPoint joinPoint, TrackTime trackTime) throws Throwable { Object result = null; long startTime = System.currentTimeMillis(); result = joinPoint.proceed(); long timeTaken = System.currentTimeMillis() - startTime; System.out.println(" --------------> Time Taken by " + joinPoint + " with param[" + trackTime.param() + "] is " + timeTaken); return result; }}By using this annotation on a method, you can collect the execution time of this method:
@TrackTime(param = "myService")public String runFoo() { System.out.println(" ----------------> foo"); return "foo";}Note that the @TrackTime(param = "myService") annotation can be passed.
In order for annotations to pass parameters, you need to specify a parameter String param() default "default" when defining annotations.
At the same time, in the Aspect class, the corresponding parameters are added to the around method. The variable name of the parameter is also required to be trackTime in the @Around annotation, but not the class name TrackTime.
@Around("@annotation(trackTime)")public Object around(ProceedingJoinPoint joinPoint, TrackTime trackTime)5. Summary
When running the sample project, the console outputs the following:
----------------> Before Aspect
--------------> before execution of execution(String cn.springcamp.springaop.service.MyService.runFoo())
---------------> foo
---------------> Time Taken by execution(String cn.springcamp.springaop.service.MyService.runFoo()) with param[myService] is 8
---------------> After Aspect
--------------> after execution of execution(String cn.springcamp.springaop.service.MyService.runFoo())
---------------> AfterReturning Aspect
----------------> execution(String cn.springcamp.springaop.service.MyService.runFoo()) returned with value foo
It can be seen that the execution order of several Aspects is Before After Around AfterReturning(AfterThrowing)
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.