SpringBoot學習之整合AOP
SpringBoot學習之整合AOP
基於SpringBoot整合Aop記錄日誌
-
SpringBoot各版本參考文件
https://docs.spring.io/spring-boot/docs/
-
查詢引入依賴
-
引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
-
切面類
package link.lycreate.springbooteasyexceldemo.aspect; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Arrays; /** * @ClassName LogAspect * @Description TODO 日誌切面類$ * @Author charlesYan * @Date 2020/10/9 12:53 * @Version 1.0 **/ @Aspect // 宣告是一個切面元件 @Component // 加入到IOC容器 @Slf4j // 等同於 private final Logger logger = LoggerFactory.getLogger(XXX.class); public class LogAspect { /** * @Author charlesYan * @Description // 指定切入點表示式,攔截那些方法,即為哪些類生成代理物件 * 第一*表示匹配任何返回值的方法 * 第二*表示匹配controller包下的所有類 * 第三*表示匹配類下的所有方法 * ..表示任何個數引數,和如何型別的引數 **/ //@Pointcut("execution(* link.lycreate.springbooteasyexceldemo.controller.*.*(..))") @Pointcut("@annotation(link.lycreate.springbooteasyexceldemo.aspect.LogFilter)") //在所有標記指定註解的方法上攔截 public void logPointCut(){} /** * @Author charlesYan * @Description //前置通知:在目標方法執行前呼叫 **/ @Before("logPointCut()") public void before(JoinPoint joinPoint){ System.out.println("---------------Before Begin CurrentTime = " + System.currentTimeMillis()); /*獲取當前請求的HttpServletRequest*/ RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest(); log.info("URL-->"+request.getRequestURL().toString()); log.info("IP-->"+request.getRemoteAddr()); log.info("HTTP_Method-->"+request.getMethod()); log.info("Request_args-->"+ Arrays.toString(joinPoint.getArgs())); System.out.println("---------------Before End CurrentTime = " + System.currentTimeMillis()); } /** * @Author charlesYan * @Description //返回通知 在目標方法執行後呼叫,若目標方法出現異常,則不執行 **/ @AfterReturning(value = "logPointCut()",returning = "obj") public void afterReturning(JoinPoint joinPoint,Object obj){ System.out.println("---------------AfterReturn CurrentTime = " + System.currentTimeMillis()); } /** * @Author charlesYan * @Description //後置通知:無論目標方法在執行過程中是否出現異常都會在它之後呼叫 **/ @After("logPointCut()") public void after(JoinPoint joinPoint){ System.out.println("---------------After CurrentTime = " + System.currentTimeMillis()); } /** * @Author charlesYan * @Description //異常通知:目標方法丟擲異常時執行 **/ @AfterThrowing(value = "logPointCut()", throwing = "ex") public void afterThrowing(JoinPoint joinPoint,Exception ex){ System.out.println("---------------AfterThrowing CurrentTime = " + System.currentTimeMillis()); } /** * @Author charlesYan * @Description //環繞通知:是前面四個通知的結合體 * 需要在方法之前執行,可以寫在joinPoint.procedd();之前 * 需要在方法之後執行,可以寫在joinPoint.procedd();之後 **/ @Around("logPointCut()") public void around(ProceedingJoinPoint joinPoint) throws Throwable { // 獲取目標方法的名稱 String methodName = joinPoint.getSignature().getName(); // 獲取方法傳入引數 Object[] params = joinPoint.getArgs(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 獲取方法上LogFilter註解 LogFilter logFilter = method.getAnnotation(LogFilter.class); String value = logFilter.value() ; log.info("模組描述:"+value); System.out.println("---------------Around Before CurrentTime = " + System.currentTimeMillis() + " method name:" + methodName + " args:" + params[0]); // 執行源方法 joinPoint.proceed(); System.out.println("---------------Around After CurrentTime = " + System.currentTimeMillis() + " method name:" + methodName + " args:" + params[0]); } }
-
自定義註解
/** * @ClassName LogFilter * @Description TODO 自定義日誌註解類$ * @Author charlesYan * @Date 2020/10/11 17:59 * @Version 1.0 **/ @Target(ElementType.METHOD)//Target註解決定LogFilter註解可以加在哪些成分上,如加在類身上,或者屬性身上,或者方法身上等成分 @Retention(RetentionPolicy.RUNTIME)//Retention註解括號中的"RetentionPolicy.RUNTIME"意思是讓LogFilter這個註解的生命週期一直程式執行時都存在 @Documented public @interface LogFilter { String value() default ""; }
-
請求方法
@LogFilter("儲存請求日誌") @RequestMapping(path = "/saveRequestLog",method = RequestMethod.POST) public String saveRequestLog(@RequestParam("name")String name){ return "請求成功:" + name; }
-
測試方式
報錯資訊
方法引數未宣告
-
報錯資訊
Caused by: java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
-
截圖資訊
-
錯誤程式碼
/** * @Author charlesYan * @Description //返回通知 在目標方法執行後呼叫,若目標方法出現異常,則不執行 **/ @AfterReturning("logPointCut()") public void afterReturning(JoinPoint joinPoint,Object obj){ System.out.println("---------------AfterReturn CurrentTime = " + System.currentTimeMillis()); }
-
正確程式碼
/** * @Author charlesYan * @Description //返回通知 在目標方法執行後呼叫,若目標方法出現異常,則不執行 **/ @AfterReturning(value = "logPointCut()", returning = "obj") public void afterReturning(JoinPoint joinPoint,Object obj){ System.out.println("---------------AfterReturn CurrentTime = " + System.currentTimeMillis()); }
-
原因分析
新增的方法引數未賦值
總結
Aop切面通知執行順序
- 例圖
通知註解中的value屬性補充
-
自定義註解
//註解實體類 package com.trip.demo; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD }) public @interface SMSAndMailSender { /*簡訊模板String格式化串*/ String value() default ""; String smsContent() default ""; String mailContent() default ""; /*是否啟用傳送功能*/ boolean isActive() default true; /*主題*/ String subject() default ""; }
-
切面類中的切面方法
/** * 在所有標記了@SMSAndMailSender的方法中切入 * @param joinPoint * @param obj */ @AfterReturning(value="@annotation(com.trip.demo.SMSAndMailSender)", returning="obj") public void afterReturning(JoinPoint joinPoint,Object obj){ System.out.println("---------------AfterReturn CurrentTime = " + System.currentTimeMillis()); }
參考連結
-
SpringBoot整合Aop
https://www.cnblogs.com/fernfei/p/12092510.html
-
SpringBoot整合aop
https://www.cnblogs.com/myitnews/p/11848159.html
-
SpringBoot 通過自定義註解實現AOP切面程式設計例項
https://www.cnblogs.com/lingyejun/p/9941350.html
-
SpringBoot2.0 基礎案例(11):配置AOP切面程式設計,解決日誌記錄業務
https://my.oschina.net/cicadasmile/blog/3073069
-
淺談Spring AOP 面向切面程式設計 最通俗易懂的畫圖理解AOP、AOP通知執行順序~
https://www.cnblogs.com/ChromeT/p/11823735.html
-
@interface 註解詳解
https://blog.csdn.net/u010882691/article/details/82427520
相關文章
- SpringBoot學習之整合MybatisSpring BootMyBatis
- SpringBoot學習之整合SwaggerSpring BootSwagger
- Spring-boot整合AOP及AOP相關學習Springboot
- SpringBoot整合Activiti學習(一)Spring Boot
- Rabbit學習---SpringBoot整合RabbitMQSpring BootMQ
- jackson學習之九:springboot整合(配置檔案)Spring Boot
- Elasticsearch學習<四>SpringBoot整合esElasticsearchSpring Boot
- 個人學習系列 - SpringBoot整合RabbitMQSpring BootMQ
- Elasticsearch學習(三)springboot整合ElasticSearchElasticsearchSpring Boot
- 【springboot】學習4:整合JDBC、整合druid、整合mybatis、整合 SpringSecuritySpring BootJDBCUIMyBatisGse
- jackson學習之十(終篇):springboot整合(配置類)Spring Boot
- Android AOP學習之:AspectJ實踐Android
- SpringBoot學習之mvcSpring BootMVC
- SSM框架學習之Spring的AOP學習以及資料整理SSM框架Spring
- AOP學習筆記筆記
- SpringBoot整合ElasticSearch 入門demo學習筆記Spring BootElasticsearch筆記
- Spring之Aop練習Spring
- 整合學習(一):簡述整合學習
- Spring AOP學習筆記01:AOP概述Spring筆記
- 整合學習
- SpringBoot學習之資料結構Spring Boot資料結構
- Spring AOP學習筆記03:AOP的核心實現之獲取增強器Spring筆記
- SpringBoot使用AOPSpring Boot
- SpringBoot之Dubbo和Zookeeper整合Spring Boot
- Spring AOP學習筆記02:如何開啟AOPSpring筆記
- 機器學習-整合學習機器學習
- Spring AOP學習筆記05:AOP失效的罪因Spring筆記
- springboot中的AOPSpring Boot
- SpringBoot AOP的使用Spring Boot
- ML.NET 示例:深度學習之整合TensorFlow深度學習
- ML《整合學習(二)Boosting之Adaboosting》
- SpringBoot 學習Spring Boot
- springboot學習Spring Boot
- SpringBoot部落格開發之AOP日誌處理Spring Boot
- Spring5.0原始碼學習系列之Spring AOP簡述Spring原始碼
- SpringBoot系列之YAML配置用法學習筆記Spring BootYAML筆記
- Springcloud學習筆記68--springboot 整合Caffeine 本地快取GCCloud筆記Spring Boot快取
- SpringBoot之整合thymeleaf渲染Web頁面Spring BootWeb