Spring AOP不進入before和業務方法,卻進入其他切面的問題
由於業務需求,需要編寫一個AOP用來記錄一些外部介面的呼叫日誌.
首先是引入切面要用到的jar包,maven工程加入如下所示:
然後是配置檔案,由於要在controller層加上切面,因此需要在springMVC的配置檔案上加上
<aop:aspectj-autoproxy proxy-target-class="true" />
如此,配置檔案的修改就完成了.
接下來就是編寫切面類了,程式碼如下:
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 切面類
* <p>
* 記錄日誌
*/
// 宣告這是一個元件
@Component
// 宣告這是一個切面Bean
@Aspect
public class LogAspect {
/**
* 日誌記錄工具
*/
private static final Logger LOGGER = LogManager.getLogger(LogAspect.class);
/**
* 預設建構函式
*/
public LogAspect() {
System.out.println("初始化切面");
}
/**
* 配置切入點,該方法無方法體,主要為方便同類中其他方法使用此處配置的切入點,第一種配置切入點的方法
* <p>
* 掃描com.test.controller.TestController下面的所有方法
* @see [類、類#方法、類#成員]
*/
@Pointcut("execution(* com.test.controller.Test1Controller..*(..))")
public void aspectTest1() {
}
/**
* 配置前置通知,使用在方法aspect()上註冊的切入點,第二種配置切入點的方法
* <p>
* 同時接受JoinPoint切入點物件,可以沒有該引數
*
* @param joinPoint切入點
* @see [類、類#方法、類#成員]
*/
@Before("execution(* com.test.controller.Test2Controller..*(..))")
private void beforeTest2(JoinPoint joinPoint) {
String className = joinPoint.getTarget().getClass().getName(); //類名
String methodName = joinPoint.getSignature().getName(); //方法名
}
@Before("aspectTest1()")
private void beforeTest1(JoinPoint joinPoint) {
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
}
/**
* 配置後置通知,使用在方法aspect()上註冊的切入點
* <p>
* </p>
*
* @param joinPoint
* 切入點
* @see [類、類#方法、類#成員]
*/
@After("aspectTest1()")
private void after(JoinPoint joinPoint) {
System.out.println("after");
}
/**
* 配置環繞通知,使用在方法aspect()上註冊的切入點
* <p>
* 記錄方法開始到結束的耗時
*
* @param joinPoint
* 切入點
* @return Object 處理結果
* @throws Throwable
* 異常
* @see [類、類#方法、類#成員]
*/
@Around("aspectTest1()")
private Object around(JoinPoint joinPoint) throws Throwable {
System.out.println("環繞通知前....");
ProceedingJoinPoint tempJoinPoint = (ProceedingJoinPoint) joinPoint;
/*Object object = tempJoinPoint.proceed();*/
System.out.println("環繞通知後....");
//return object;
return null;
}
/**
* <配置後置返回通知,使用在方法aspect()上註冊的切入點
* <p>
*
* @param joinPoint
* 切入點
* @see [類、類#方法、類#成員]
*/
@AfterReturning(returning = "rvt", value = "aspectTest1()")
public void afterReturn(JoinPoint joinPoint, Object rvt) {
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
String args = "";
for (int i = 0; i < joinPoint.getArgs().length; i++) {
args = args + joinPoint.getArgs()[i] + ",";
}
args = args.substring(0, args.length() - 1);
String OutParam="";
if(rvt!=null){
OutParam=rvt.toString();
}
System.out.println("rvt");
}
/**
* 配置丟擲異常後通知,使用在方法aspectTest1()上註冊的切入點
* <p>
* </p>
*
* @param joinPoint
* 切入點
* @param ex
* 異常
* @see [類、類#方法、類#成員]
*/
@AfterThrowing(pointcut = "aspectTest1()", throwing = "ex")
public void afterThrow(JoinPoint joinPoint, Exception ex) {
System.out.println("afterThrow");
}
}
切面類至此就寫完了,
然後就是要切入的類和方法,這裡就不寫了.
寫完之後執行,測試,發現,before的切入點並沒有進去,而其他的切入點(除了AfterThrowing)均有輸出,要切入的業務方法也沒進去,
剛開始以為配置問題,不停地修改配置,什麼加包掃描啊,配置實體啊,各種方法都不行,最後發現是因為自己偷懶,將環繞通知的程序方法註釋調了,導致程式在進入切面之後,無法正常執行,將這個註釋去掉之後,切面就可以正常使用了.