springboot使用AOP
依赖引入
<!--添加aop依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
SpringMvc提供获取request和response对象
//这个RequestContextHolder是Springmvc提供来获得请求的东西
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();
//从session里面获取对应的值
String str = (String) requestAttributes.getAttribute("name",RequestAttributes.SCOPE_SESSION);
System.out.println("uri==>"+request.getRequestURI());
System.out.println("url==>"+request.getRequestURL());
代码实操
package com.lwp.study.proxy.log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.SourceLocation;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
@Aspect
@Component
public class CustomAdvice {
/**
* 定义切面点
*/
@Pointcut("execution(* com.lwp.study.controller.StudentRestFulController.*(..))")
public void controllerLog(){
}
/**
* 方法执行之前的切面处理
* @param joinPoint
*/
@Before("controllerLog()")
public void before(JoinPoint joinPoint){
//这个RequestContextHolder是Springmvc提供来获得请求的东西
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
System.out.println("uri==>"+request.getRequestURI());
System.out.println("url==>"+request.getRequestURL());
//获取请求的参数
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println("args===>"+arg);
}
//获取签名信息
Signature signature = joinPoint.getSignature();
//目标类的类型 class com.lwp.study.controller.StudentRestFulController
Class declaringType = signature.getDeclaringType();
//目标的类型名称 com.lwp.study.controller.StudentRestFulController
String declaringTypeName = signature.getDeclaringTypeName();
//方法名称 addUser
String name = signature.getName();
//方法执行 method-execution
String kind = joinPoint.getKind();
System.out.println("方法执行之前");
}
/**
* 方法执行之后的切面处理
* @param joinPoint
* @param returnObj
*/
@AfterReturning(returning = "returnObj", pointcut="controllerLog()")
public void after(JoinPoint joinPoint,Object returnObj){
//返回值结果
System.out.println("返回值结果==>"+returnObj);
System.out.println("方法执行之后");
}
/**
* 异常处理==》切面操作的类中抛出异常则会执行
* @param joinPoint
* @param ex
*/
@AfterThrowing(pointcut = "controllerLog()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("连接点方法为:" + methodName + ",参数为:" + args + ",异常为:" + ex);
}
/**
* 这个注解可以简单地看作@Before和@After的结合。这个注解和其他的比比较特别,它的方法的参数一定要是ProceedingJoinPoint,
* 这个对象是JoinPoint的子类。我们可以把这个看作是切入点的那个方法的替身,这个proceedingJoinPoint有个proceed()方法,
* 相当于就是那切入点的那个方法执行,简单地说就是让目标方法执行,然后这个方法会返回一个对象,
* 这个对象就是那个切入点所在位置的方法所返回的对象。
*
* 除了这个Proceed方法(很重要的方法),其他和那几个注解一样。
* @param joinPoint
*/
@Around("controllerLog()")
public Object around(ProceedingJoinPoint joinPoint){
System.out.println("around执行前");
try {
//执行方法,接收对象为返回值
Object proceed = joinPoint.proceed();
System.out.println("around执行后");
System.out.println("proceed==>"+proceed);
return proceed; //一定要返回,不然前端接收不到数据
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
同一个方法有多个@Aspect类拦截
单个Aspect肯定是和只有一个Aspect的时候的情况是一样的,但不同的Aspect里面的advice的顺序呢??答案是不一定,像是线程一样,没有谁先谁后,除非你给他们分配优先级,同样地,在这里你也可以为@Aspect分配优先级,这样就可以决定谁先谁后了。
优先级有两种方式:
实现org.springframework.core.Ordered接口,实现它的getOrder()方法
给aspect添加@Order注解,该注解全称为:org.springframework.core.annotation.Order
不管是哪种,都是order的值越小越先执行:
@Order(5)
@Component
@Aspect
public class Aspect1 {
// ...
}
@Order(6)
@Component
@Aspect
public class Aspect2 {
// ...
}
这样Aspect1就永远比Aspect2先执行了。
本文参考博客
https://www.cnblogs.com/wangshen31/p/9379197.html2