1. 程式人生 > >Spring AOP不進入before和業務方法,卻進入其他切面的問題

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)均有輸出,要切入的業務方法也沒進去,

剛開始以為配置問題,不停地修改配置,什麼加包掃描啊,配置實體啊,各種方法都不行,最後發現是因為自己偷懶,將環繞通知的程序方法註釋調了,導致程式在進入切面之後,無法正常執行,將這個註釋去掉之後,切面就可以正常使用了.

所以,以後在配置切面時,要麼不寫環繞的部分,要麼就要寫完,千萬不要偷懶.
--------------------- 
作者:yaotou402 
來源:CSDN 
原文:https://blog.csdn.net/u010524100/article/details/79527300 
版權宣告:本文為博主原創文章,轉載請附上博文連結!