前言:在開發過程中,需要對每個方法執行時進行日志記錄,故而整理一下有關AOP的相關知識點。
一、基本概念:
1、切面類 @Aspect: 定義切面類,加上@Aspect、@Component注解;//下文有展示
2、切點 @Pointcut:
// 指定切面方法
@Pointcut("execution(public * com.rest.module..*.*(..))")
public void getMethods() {
}
注:execution表達式第一個*表示匹配任意的方法返回值,..(兩個點)表示零個或多個,第一個..表示module包及其子包,第二個*表示所有類, 第三個*表示所有方法,第二個..表示方法的任意參數個數
// 指定注解
@Pointcut("@annotation(com.rest.utils.SysPlatLog)")
public void withAnnotationMethods() {
}
注:在這里,自定義了一個注解類,方法加注解即可使用;
/**
* 系統平台日志記錄
*/
public @interface SysPlatLog {
// 操作名稱
String operateName() default "";
// 操作描述
String logNote() default "";
}
3、Advice,在切入點上執行的增強處理,主要有五個注解:
@Before 在切點方法之前執行
@After 在切點方法之后執行
@AfterReturning 切點方法返回后執行
@AfterThrowing 切點方法拋異常執行
@Around 屬於環繞增強,能控制切點執行前,執行后
4、JoinPoint :方法中的參數JoinPoint為連接點對象,它可以獲取當前切入的方法的參數、代理類等信息,因此可以記錄一些信息,驗證一些信息等;
5、使用&&、||、!、三種運算符來組合切點表達式,表示與或非的關系;
6、@annotation(annotationType) 匹配指定注解為切入點的方法;
7、//aop代理對象
Object aThis = joinPoint.getThis();
//被代理對象
Object target = joinPoint.getTarget();
8、調用切面注解:
@SysPlatLog(operateName = "查看詳情",logNote = "查看詳情")
@SneakyThrows
public Result getItem(@RequestParam(required = false) String bs){
}
二、代碼展示:
1 package com.npc.rest.utils; 2 3 import com.npc.rest.common.properites.AppSupPlatProperties; 4 import com.sys.model.SysLog; 5 import lombok.extern.slf4j.Slf4j; 6 import org.aspectj.lang.JoinPoint; 7 import org.aspectj.lang.annotation.*; 8 import org.springframework.stereotype.Component; 9 import java.lang.reflect.Method; 10 import java.util.*; 11 12 @Aspect 13 @Slf4j 14 @Component 15 public class SysPlatLogAspect { 16 17 /** 18 * 指定切面 19 */ 20 @Pointcut("execution(public * com.rest.module..*.*(..))") 21 public void getMethods() { 22 } 23 /** 24 * 指定注解 25 */ 26 @Pointcut("@annotation(com.rest.utils.SysPlatLog)") 27 public void withAnnotationMethods() { 28 } 29 30 /*** 31 * 攔截控制層的操作日志 32 * @param joinPoint 33 * @return 34 * @throws Throwable 35 */ 36 @After(value = "getMethods() && withAnnotationMethods()") 37 public void recordLog(JoinPoint joinPoint) throws Throwable { 38 SysLog sysLog = new SysLog(); 39 SysPlatLog sysPlatLog = getInter(joinPoint); 40 sysLog.setOperateName(sysPlatLog.operateName()); 41 sysLog.setLogNote(sysPlatLog.logNote()); 42 sysLog.setLogTime(new Date()); 43 sysLog.setAppCode(AppSupPlatProperties.getAppCode()); 44 } 45 46 public SysPlatLog getInter(JoinPoint joinPoint) throws ClassNotFoundException { 47 String targetName = joinPoint.getTarget().getClass().getName(); 48 String methodName = joinPoint.getSignature().getName(); 49 Object[] arguments = joinPoint.getArgs(); 50 Class targetClass = Class.forName(targetName); 51 Method[] methods = targetClass.getMethods(); 52 for (Method method : methods) { 53 if (method.getName().equals(methodName)) { 54 Class[] clazzs = method.getParameterTypes(); 55 if (clazzs.length == arguments.length) { 56 SysPlatLog sysPlatLog = method.getAnnotation(SysPlatLog.class); 57 return sysPlatLog; 58 } 59 } 60 } 61 return null; 62 } 63 }