AOP has @before, @after, @around, @afterrunning annotations, and so on.

First up and down their own code, defined the definition of the pointcut

@Aspect @Component public class LogApsect { private static final Logger logger = LoggerFactory.getLogger(LogApsect.class); ThreadLocal<Long> startTime = new ThreadLocal<>(); // The first * represents the return type without limitation // the second * represents all classes // the third * represents all methods // (..) @pointcut ("execution(public * com.lmx.blog.controller.*.*(..)) )") @Order(2) public void pointCut(){}; The @pointcut (" @ the annotation (com) LMX) blog. The annotation. RedisCache) ") @ Order (1) / / the Order priority, Public void annoationPoint(){}; @Before(value = "annoationPoint() || pointCut()") public void before(JoinPoint joinPoint){ System.out.println("...... is executed before the method is executed before"); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); logger.info("<====================================================="); Logger.info (" request source: = "+ request.getremoteaddr ()); Logger.info (" RequestURL: "+ request.getrequestURL ().toString()); Logger.info (" Request method: "+ request.getMethod()); Logger.info (" response method: "+ joinPoint.getSignature().getName() + "." + JoinPoint.getSignature ().getName()); Logger. info(" Request parameters: "+ Array.tostring (JoinPoint.getargs ())); logger.info("------------------------------------------------------"); startTime.set(System.currentTimeMillis()); } // Define the pointcut expression to match, @around ("pointCut() && args(arg)") public Response Around(ProceedingJoinPoint PJP,String ARg) throws Throwable{  System.out.println("name:" + arg); System.out.println(" method around start... around"); String result = null; try{ result = pjp.proceed().toString() + "aop String"; System.out.println(result); }catch (Throwable e){ e.printStackTrace(); } system.out. println(" method around end... around"); return (Response) pjp.proceed(); } @after ("within(com.lmx.blog.controller.* controller)") public void After(){system.out.println ();} @after ("within(com.lmx.blog.controller. after."); } @AfterReturning(pointcut="pointCut()",returning = "rst") public void afterRunning(Response rst){ if(startTime.get() ==  null){ startTime.set(System.currentTimeMillis()); } system.out. println(" method is executed... afterRunning"); Logger.info (" Time (ms) : "+ (system.currentTimemillis () -startTime.get ())); Logger. info(" return data: {}", RST); logger.info("==========================================>"); } @AfterThrowing("within(com.lmx.blog.controller.*Controller)") public void afterThrowing(){ System.out.println(" after the exception occurs... afterThrowing"); }}Copy the code

Spring Boot: github.com/javastacks/…

@before, @after, @around The difference between annotations you can baidu. Anyway, @around can do what @before and @after can do in one method.

First let’s test a method for retrieving a database record

@requestMapping ("/achieve") public Response achieve(){system.out.println (" -----------"); return Response.ok(articleDetailSercice.getPrimaryKeyById(1L)); }Copy the code

The following is the log printed by the console

Before the method is executed, run...... Before the 2018-11-23 16:31:59. 795 [HTTP - nio - 8888 - exec - 9] INFO C.L.B the config. LogApsect - < = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 2018-11-23 16:31:59, 795 [HTTP - nio - 8888 - exec - 9] INFO C.L.B log. Config. LogApsect - request sources: = 0:0:0:0:0:0:1-0 16:31:59. 2018-11-23, 795 [HTTP - nio - 8888 - exec - 9] INFO C.L.B the config. LogApsect - request URL: http://localhost:8888/user/achieve 16:31:59 2018-11-23. 795 - nio - 8888 - [HTTP exec - 9] INFO C.L.B the config. LogApsect - request: GET the 2018-11-23 16:31:59. 795 [HTTP - nio - 8888 - exec - 9] INFO C.L.B the config. LogApsect - response method: Com. LMX. Blog. Controller. UserController. Your 16:31:59. 2018-11-23, 796 [HTTP - nio - 8888 - exec - 9] INFO C.L.B log. Config. LogApsect - request parameters: [] the 2018-11-23 16:31:59. 796 [HTTP - nio - 8888 - exec - 9] INFO C.L.B the config. LogApsect - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- method -- -- -- -- -- -- -- -- -- -- - the 2018-11-23 16:31:59. 806 - nio - 8888 - [HTTP exec - 9] DEBUG c.l.b.m.A.selectPrimaryKey - ==> Preparing: select * from article_detail where id = ? The 2018-11-23 16:31:59. 806 [HTTP - nio - 8888 - exec - 9] the DEBUG C.L.B.M.A.S electPrimaryKey - = = > Preparing: select * from article_detail where id = ? The 2018-11-23 16:31:59. 806 [HTTP - nio - 8888 - exec - 9] the DEBUG C.L.B.M.A.S electPrimaryKey - = = > the Parameters: 1 (Long) the 2018-11-23 16:31:59. 806 [HTTP - nio - 8888 - exec - 9] the DEBUG C.L.B.M.A.S electPrimaryKey - = = > the Parameters: 1 (Long) the 2018-11-23 16:31:59. 814 [HTTP - nio - 8888 - exec - 9] the DEBUG C.L.B.M.A.S electPrimaryKey - < = = Total: 1 the 16:31:59 2018-11-23. 814 - nio - 8888 - [HTTP exec - 9] the DEBUG C.L.B.M.A.S electPrimaryKey - < = = Total: 1 method executed after... After. Method executed after execution... AfterRunning 16:31:59 2018-11-23. 824 - nio - 8888 - [HTTP exec - 9] INFO C.L.B the config. LogApsect - time-consuming (ms) : 27 2018-11-23 16:31:59. 824 [HTTP - nio - 8888 - exec - 9] INFO C.L.B the config. LogApsect - return data: Com.lmx.blog.com mon. The Response @ 8675 ce5 16:31:59 2018-11-23. 824 - nio - 8888 - [HTTP exec - 9] INFO C.L.B the config. LogApsect - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = >Copy the code

As you can see, there is no wrap notification because there is no rule matching @around. (PS: The circular notification I defined means that the method must conform to the controller package and the method must have parameters. The above method has no parameters, so only the @before and @after methods are used, which does not conform to the matching logic of @around.)

Let’s try another method with arguments

@RedisCache(type = Response.class) @RequestMapping("/sendEmail") public Response sendEmailToAuthor(String content){ System.out.println(" test execution times "); return Response.ok(true); }Copy the code

Here is the console print of that part of the code

Name: Second email method around start... Before executing the around method, execute...... Before the 2018-11-23 16:34:55. 347 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - < = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 2018-11-23 16:34:55, 347 [HTTP - nio - 8888 - exec - 2] INFO C.L.B log. Config. LogApsect - request sources: = 0:0:0:0:0:0:1-0 16:34:55. 2018-11-23, 347 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - request URL: http://localhost:8888/user/sendEmail 2018-11-23 16:34:55. 348 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - [HTTP request methods: GET 2018-11-23 16:34:55. 348 - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - response method: Com. LMX. Blog. Controller. UserController. SendEmailToAuthor 16:34:55. 2018-11-23, 348 [HTTP - nio - 8888 - exec - 2] INFO C.L.B log. Config. LogApsect - request parameters: [?] the second email, 2018-11-23 16:34:55. 348 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - test execution times com.lmx.blog.com mon. The Response @ 6 d17f2fdaop String methods around the end... Before executing the around method, execute...... Before the 2018-11-23 16:34:55. 349 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - < = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 2018-11-23 16:34:55, 349 [HTTP - nio - 8888 - exec - 2] INFO C.L.B log. Config. LogApsect - request sources: = 0:0:0:0:0:0:1-0 16:34:55. 2018-11-23, 349 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - request URL: http://localhost:8888/user/sendEmail 2018-11-23 16:34:55. 349 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - [HTTP request methods: GET 2018-11-23 16:34:55. 349 - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - response method: Com. LMX. Blog. Controller. UserController. SendEmailToAuthor 16:34:55. 2018-11-23, 349 [HTTP - nio - 8888 - exec - 2] INFO C.L.B log. Config. LogApsect - request parameters: [?] the second email, 2018-11-23 16:34:55. 350 [HTTP - nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- after the number of test execution method perform... After. Method executed after execution... AfterRunning 16:34:55 2018-11-23. 350 - nio - 8888 - [HTTP exec - 2] INFO C.L.B the config. LogApsect - time-consuming (ms) : 0 2018-11-23 16:34:55. [HTTP - 350 nio - 8888 - exec - 2] INFO C.L.B the config. LogApsect - return data: Com.lmx.blog.com mon. The Response @ 79 f85428 16:34:55 2018-11-23. 350 - nio - 8888 - [HTTP exec - 2] INFO C.L.B the config. LogApsect - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = >Copy the code

It was obvious that the method matched the @around notification rules, so it went into the @around logic, but found a problem, and all the methods were executed twice, both at the cut and method levels. @rediscache (type = response.class). Why does this match @around? I’ll talk about that later.)

Analysis of the print order of the log shows that, when executing the wrap method, the method under @around takes precedence. The @around method.

// Define the pointcut expression to match, @around ("pointCut() && args(arg)") public Response Around(ProceedingJoinPoint PJP,String ARg) throws Throwable{  System.out.println("name:" + arg); System.out.println(" method around start... around"); String result = null; try{ result = pjp.proceed().toString() + "aop String"; System.out.println(result); }catch (Throwable e){ e.printStackTrace(); } system.out. println(" method around end... around"); return (Response) pjp.proceed(); }Copy the code

Print the first two lines of code later, to perform the @ Before method, because the way triggered ProceedingJoinPoint. Proceed () method. The purpose of this method is to execute the proxied method, which means that after executing this method it will execute our controller method, then @before, @after, then back to @around to execute the unexecuted method, and finally @afterRUNNING, If an exception is thrown, @afterThrowing can be executed

That is surrounded by the execution order is @ Around – the @ Before – @ After – executive ProceedingJoinPoint. @ Around the proceed () After the operation – @ AfterRunning (if there is abnormal – > @ AfterThrowing)

And we are the log is equivalent to the above results carried out 2 times, the root cause is that ProceedingJoinPoint. Proceed () this method, can be found in the @ Around method we use 2 times this method, However, every time this method is called up a @ Before – @ After – executive ProceedingJoinPoint. @ Around the proceed () After the operation – @ AfterRunning (if there is abnormal – > @ AfterThrowing). So the problem arises here. So changing the code in the @around section solves the problem. The changed code looks like this:

@Around("pointCut() && args(arg)") public Response around(ProceedingJoinPoint pjp,String arg) throws Throwable{ System.out.println("name:" + arg); System.out.println(" method around start... around"); String result = null; Object object = pjp.proceed(); try{ result = object.toString() + "aop String"; System.out.println(result); }catch (Throwable e){ e.printStackTrace(); } system.out. println(" method around end... around"); return (Response) object; }Copy the code

The result of running the code after changing it

Name: Second email method around start... Before executing the around method, execute...... Before the 2018-11-23 16:52:14. 315 [HTTP - nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - < = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 2018-11-23 16:52:14, 315 [HTTP - nio - 8888 - exec - 4] INFO C.L.B log. Config. LogApsect - request sources: = 0:0:0:0:0:0:1-0 16:52:14. 2018-11-23, 315 [HTTP - nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - request URL: http://localhost:8888/user/sendEmail 2018-11-23 16:52:14. 315 [HTTP - nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - [HTTP request methods: GET 2018-11-23 16:52:14. 316 - nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - response method: Com. LMX. Blog. Controller. UserController. SendEmailToAuthor 16:52:14. 2018-11-23, 316 [HTTP - nio - 8888 - exec - 4] INFO C.L.B log. Config. LogApsect - request parameters: [?] the second email, 2018-11-23 16:52:14. 316 [HTTP - nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - test execution times com.lmx.blog.com mon. The Response @ 1 b1c76afaop String methods around the end... After the around method executes... After. Method executed after execution... AfterRunning 16:52:14 2018-11-23. 316 - nio - 8888 - [HTTP exec - 4] INFO C.L.B the config. LogApsect - time-consuming (ms) : 0 2018-11-23 16:52:14. [HTTP - 316 nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - return data: Com.lmx.blog.com mon. The Response @ 1 b1c76af 16:52:14. 2018-11-23, 316 [HTTP - nio - 8888 - exec - 4] INFO C.L.B the config. LogApsect - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = >Copy the code

Returning to the open question above, why does another annotation that I defined for the aspect get into the @around method?

Because our method is still under controller, it satisfies this requirement, which is only useful if we define a controller under the Controller package. Such as:

@Pointcut("execution(public * com.lmx.blog.controller.UserController.*(..) )"Copy the code

If the method we just defined was written under TestController, it wouldn’t match the @around method, it wouldn’t match the @before and @After annotations, so it wouldn’t match any of the rules, and if we needed to match a particular method, You can use custom annotations or methods under the controller feature

① : Annotation form of feature

The @pointcut (" @ the annotation (com) LMX) blog. The annotation. RedisCache) ") @ Order (1) / / the Order priority, Public void annoationPoint(){};Copy the code

Then add the method being need @ RedisCache annotations, in the @ Before the @ After, @ Around methods such as adding the tangent point of the method name (” annoationPoint () “), if there are multiple notes are need to match the | |

② : Specify controller or methods under controller

@Pointcut("execution(public * com.lmx.blog.controller.UserController.*(..) )") @Order(2) public void pointCut(){};Copy the code

This part of the code specifies all methods under UserController under the com.lmx.blog.controller package.

The first * indicates that the return type is unlimited

The second * represents all methods under the controller, (..) It stands for unlimited parameters

conclusion

When methods comply with the pointcut rule but not the surround-notification rule, the order of execution is as follows

@before → @after → @afterrunning (if any exception → @afterthrowing)

When methods comply with the pointcut rule and comply with the surround-notification rule, the order of execution is as follows

@ Around – @ Before – > @ Around – @ After execution ProceedingJoinPoint. Proceed () After the operation – @ AfterRunning (if there is abnormal – > @ AfterThrowing)

The original link: blog.csdn.net/lmx125254/a…

Copyright Notice: This article is the original article of CSDN blogger “Leonis, L”, in accordance with CC 4.0 BY-SA copyright agreement, please attach the source link of the original and this statement.

Recent hot articles recommended:

1.1,000+ Java Interview Questions and Answers (2021)

2. Don’t use if/ else on full screen again, try strategy mode, it smells good!!

3. Oh, my gosh! What new syntax is xx ≠ null in Java?

4.Spring Boot 2.5 is a blockbuster release, and dark mode is exploding!

5. “Java Development Manual (Songshan version)” the latest release, quick download!

Feel good, don’t forget to click on + forward oh!