We know that AOP (aspect oriented programming) brings great convenience to developers, especially the apes with obsessive-compulsive disorder. There are a pile of redundant code irrelevant to the actual business in the project. You want to tear it up once you see it.
It's convenient for you to sort out the relevant articles online. I can't find them all.
The following example source code portal
https://gitee.com/peterven/aoptest
Out of the box
Core dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
Scenario 1 (before interface method execution)
package com.gitee.peterven.controller.admin; @Slf4j @RestController public class AdminController { @GetMapping("admin/hello") public void hello() { log.info("I am admin method!"); } }
@Slf4j @Aspect @Component public class MyAspect { @Before("execution(public * com.gitee.peterven.controller.admin.*.*(..))") public void beforeTest() throws Throwable { log.info("before invoke"); } }
Execution log
before invoke I am admin method!
Grammar analysis
@Before // Indicates that the method is woven in before it is executed execution // Represents the method executed according to the matching rule public // The method representing the match must be public * // The return value of the matching method can be of any type com.gitee.peterven.controller.admin.* // The matching method is in any class under the package *(..) // Indicates that the matching method name is arbitrary and the input parameter has no requirements
be careful
@Before is the annotation of the method before execution, so the pointcut object ProceedingJoinPoint can not be passed into the pointcut method, otherwise it will throw an exception.
@Slf4j @Aspect @Component public class MyAspect { @Before("execution(public * com.gitee.peterven.controller.admin.*.*(..))") public void beforeTest(ProceedingJoinPoint joinPoint) throws Throwable { joinPoint.proceed(); log.info("before invoke"); } }
Error creating bean with name 'tomcatServletWebServerFactory' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class]: BeanPostProcessor before instantiation of bean failed; nested exception is java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advice
Scenario 2 (before and after implementation of interface method)
package com.gitee.peterven.controller; @Slf4j @RestController public class BaseController { @GetMapping("base/hello") public User hello (Integer i) { try { log.info("basecontroller method start"); } catch (Exception e) { log.info("basecontroller method exception"); throw e; } finally { log.info("basecontroller method finally"); } return new User("gitee", 20); } }
// Any method under controller package @Around("execution(public * com.gitee.peterven.controller.*.*(..))") public Object systemTimer(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); log.info("Method to perform pre work"); Object result = joinPoint.proceed(); log.info("Methods are executed in total{}millisecond", System.currentTimeMillis() - start); log.info("Method performs post-processing"); return result; // Remember to return the result }
Execution log
Method to perform pre work basecontroller method start basecontroller method finally The method executed for a total of 9 milliseconds Method performs post-processing
Grammar analysis
@Around // Indicates that the method is woven before and after execution execution // Represents the method executed according to the matching rule public // The method representing the match must be public * // The return value of the method representing the match can be of any type com.gitee.peterven.controller.* // The matching method is in any class under the package *(..) // Indicates that the matching method name is arbitrary and the input parameter has no requirements
The following theoretical knowledge is used as a supplement, and those you don't want to see can be omitted
What is AOP
Compared with OOP, AOP deals with some business irrelevant problems, such as logging, global exception handling, transaction management, etc. These crosscutting problems will not affect the implementation of the main logic, but will be scattered to all parts of the code and difficult to maintain. AOP is to separate these problems from business logic and achieve the purpose of decoupling from the main business logic.
Professional terms
- joint point
- Connection point, in daily use, can be understood as an object method.
- pointcut
- Tangent point, the predicate expression used to match the join point.
- Advice
- Notification refers to what a section needs to do at a specific connection point.
- Aspect
- Facet, which is a collection of multiple tangent points.
- weaving
- Weaving, the process of applying the aspect to the target object. This process can be completed at compile time (for example, using AspectJ compiler), class load time and run time. Spring AOP is completed at runtime.
- Advisor
- This concept is proposed from the AOP support of Spring 1.2. An Advisor is equivalent to a small aspect. The difference is that it only has one advice, which is often encountered in transaction management.
- Target Object
- Target object, the object notified by one or more aspects.
- AOP proxy
- AOP agent.
What is Aspectj
A framework of aop is implemented
Aspectj official website (I feel lonely watching it on the official website)
http://www.eclipse.org/aspectj/
AspectJ is a seamless aspect-oriented extension to the Javatm programming languageJava platform compatibleeasy to learn and use AspectJ enablesclean modularization of crosscutting concerns, such as error checking and handling, synchronization, context-sensitive behavior, performance optimizations, monitoring and logging, debugging support, and multi-object protocols
Class annotation @ Aspect
The annotation of aspect declaration usually creates a class to manage aop, and the annotation is added to the class, indicating that aop will be implemented in Aspectj mode.
package org.aspectj.lang.annotation; /** * Aspect declaration * * @author Alexandre Vasseur */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Aspect { /** * @return the per clause expression, defaults to singleton aspect. * Valid values are "" (singleton), "perthis(...)", etc */ public String value() default ""; }
Common method annotation
- @Before
- Before method execution
- @After
- Execute after method
- @AfterReturning
- Method before returning a value
- @AfterThrowing
- Execute after throwing an exception
- @Around
- Method before and after execution
Throw abnormal conditions
package com.gitee.peterven.controller.admin; @Slf4j @RestController public class AdminController { @GetMapping("admin/hello") public String hello() { try { log.info("controller method start"); int i = 1 / 0; } catch (Exception e) { log.info("controller method exception"); throw e; } finally { log.info("controller method finally"); } return "haha"; } }
results of enforcement
@Around before invoke @Before.... controller method start controller method exception controller method finally @AfterThrowing.... @After....
If no exception is thrown, the result is as follows
@Around before invoke @Before.... controller method start controller method finally @AfterReturnning... @After.... result is:finish @Around after invoke
Tangent expression syntax
@Pointcut("xxxx")
Tangent function
category | function | explain | remarks |
---|---|---|---|
Method tangent function | execution( ) | Represents all target class method connection points that meet a matching pattern. | |
Method tangent function | @annotation( ) | Represents the connection point of the target class method annotated with a specific annotation. | |
Method input parameter tangent point function | args( ) | Specify the connection point by identifying the type definition of the input parameter object when the target class method runs. | The experiment failed. I'll study it again when I have time |
Method input parameter tangent point function | @args( ) | The connection point is specified by judging whether the class of the input parameter object of the target class method is marked with a specific annotation. | The experiment failed. I'll study it again when I have time |
Objective tangent function | within( ) | Represents all connection points under a specific domain. | |
Objective tangent function | @within( ) | If the target class matches a Class A by type, and class A is marked with a specific annotation, all connection points of the target class match the tangent point. | |
Objective tangent function | target( ) | Represents all connection points under a specific domain. Can contain its subclasses or implementation classes. | |
Objective tangent function | @target( ) | If the target class is annotated, all connection points of the target class match the tangent point. | The experiment failed. I'll study it again when I have time |
Proxy tangent function | this( ) | If the proxy class matches the specified class by type, all connection points of the proxy target class match the tangent point. |
execution
Match the corresponding method according to the expression
usage
- @Pointcut("execution(public * com.gitee.peterven.controller.admin.AdminController.*(..))")
- Any method under AdminController class
- @Pointcut("execution(public * com.gitee.peterven.controller.admin.*.*(..))")
- Any method of any class under admin package
- @Pointcut("execution(public * com.gitee.peterven.controller.admin.AdminController.h*(..))")
- Methods starting with h under AdminController class
@annotation
Used to match the method with the specified annotation
usage
/** * Annotation on class * @ author wangwenwen * @ date 2021 / 6 / 7 14:43 * @ version v1 zero */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface AopMethodAnnotation {}
- @Pointcut("@annotation(com.gitee.peterven.annotation.AopMethodAnnotation)")
- Used to match methods annotated with AopMethodAnnotation
Args and @ args
They are all used to match the input parameter types, but I tried. They all failed to start. Let's put them first
within
Match the method according to the specified type. Note that it is to match the class, not to match the method
usage
- @Pointcut("within(com.gitee.peterven.controller.admin.*)")
- Corresponding methods under the types of all classes under the admin package
- @Pointcut("within(com.gitee.peterven.controller.admin.AdminController)")
- All methods under AdminController class
- @Pointcut("within(com.gitee.peterven.controller.admin.AdminController.*)")
- This is invalid!!! Please note that
@within
Match the class according to the user-defined annotation to make all the methods under this class enter aop
usage
/** * Annotations acting on classes * @author wangwenwen * @date 2021/6/7 14:43 * @version v1.0.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface AopClassAnnotation { }
- @Pointcut("@within(com.gitee.peterven.annotation.AopClassAnnotation)")
- All methods under the class marked by AopClassAnnotation annotation will be matched
target
Similar to within, but this method can match the target class and its subclasses, while within cannot
/** * Public controller * @author wangwenwen * @date 2021/6/7 14:50 * @version v1.0.0 */ public class BaseController { }
usage
- @Pointcut("target(com.gitee.peterven.controller.BaseController)")
- You can match the methods under the BaseController class and its subclasses
@target
I don't know why @ pointcut ("@ target (COM. Gitee. Peteven. Annotation. Aopclassannotation)") failed to start. Let's have a look when you have time.
this
The proxy class matches the specified class by type (the final effect is similar to within())
usage
- @Pointcut("this(com.gitee.peterven.controller.BaseController)")
- You can match all the methods under the BaseController class
Reference articles
- https://blog.csdn.net/qq_33704186/article/details/88413438
- https://csdnnews.blog.csdn.net/article/details/103231804