本文源碼 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base
在軟件業,AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程,經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP(面向對象編程)的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。java
1)AOP採起橫向抽取機制,取代了傳統縱向繼承體系重複性代碼 2)經典應用:事務管理、性能監視、安全檢查、緩存 、日誌等 3)aop底層將採用代理機制進行實現 4)接口 + 實現類 :spring採用 jdk 的動態代理Proxy 5)實現類:spring 採用 cglib字節碼加強
1)target:目標類 須要被代理的類。例如:UserService 2)Joinpoint:鏈接點 所謂鏈接點是指那些可能被攔截到的方法。例如:全部的方法 3)PointCut:切入點 已經被加強的鏈接點。例如:addUser() 4)advice:通知/加強 加強代碼。例如:after、before 5)Weaving:織入 指把加強advice應用到目標對象target來建立新的代理對象proxy的過程. 6)proxy 代理類 7) Aspect(切面): 是切入點pointcut和通知advice的結合 一個線是一個特殊的面。 一個切入點和一個通知,組成成一個特殊的面。
<!-- AOP依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
package com.boot.aop.config; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogFilter { String value() default "" ; }
這裏分爲兩種狀況處理,一種正常的請求日誌,和系統異常的錯誤日誌。
核心註解兩個。@Aspect和@Component。git
package com.boot.aop.config; import com.alibaba.fastjson.JSONObject; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; @Aspect @Component public class LogAspect { private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class) ; @Pointcut("@annotation(com.boot.aop.config.LogFilter)") public void logPointCut (){ } @Around("logPointCut()") public Object around (ProceedingJoinPoint point) throws Throwable { Object result = null ; try{ // 執行方法 result = point.proceed(); // 保存請求日誌 saveRequestLog(point); } catch (Exception e){ // 保存異常日誌 saveExceptionLog(point,e.getMessage()); } return result; } private void saveExceptionLog (ProceedingJoinPoint point,String exeMsg){ LOGGER.info("捕獲異常:"+exeMsg); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); LOGGER.info("請求路徑:"+request.getRequestURL()); MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); LOGGER.info("請求方法:"+method.getName()); // 獲取方法上LogFilter註解 LogFilter logFilter = method.getAnnotation(LogFilter.class); String value = logFilter.value() ; LOGGER.info("模塊描述:"+value); Object[] args = point.getArgs(); LOGGER.info("請求參數:"+ JSONObject.toJSONString(args)); } private void saveRequestLog (ProceedingJoinPoint point){ HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); LOGGER.info("請求路徑:"+request.getRequestURL()); MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); LOGGER.info("請求方法:"+method.getName()); // 獲取方法上LogFilter註解 LogFilter logFilter = method.getAnnotation(LogFilter.class); String value = logFilter.value() ; LOGGER.info("模塊描述:"+value); Object[] args = point.getArgs(); LOGGER.info("請求參數:"+ JSONObject.toJSONString(args)); } }
@LogFilter("保存請求日誌") @RequestMapping("/saveRequestLog") public String saveRequestLog (@RequestParam("name") String name){ return "success:"+name ; }
切面類信息打印github
/** * 請求路徑:http://localhost:8011/saveRequestLog * 請求方法:saveRequestLog * 模塊描述:保存請求日誌 * 請求參數:["cicada"] */
@LogFilter("保存異常日誌") @RequestMapping("/saveExceptionLog") public String saveExceptionLog (@RequestParam("name") String name){ int error = 100 / 0 ; System.out.println(error); return "success:"+name ; }
切面類信息打印web
/** * 捕獲異常:/ by zero * 請求路徑:http://localhost:8011/saveExceptionLog * 請求方法:saveExceptionLog * 模塊描述:保存異常日誌 * 請求參數:["cicada"] */
GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 碼雲地址:知了一笑 https://gitee.com/cicadasmile/spring-boot-base