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 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/haiyang4988/article/details/84324223