SpringBoot中AOP的使用

注解需要的maven坐标:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

首先需要了解execution表达式如何书写

eq:execution(public * com.example.druid.controller..*.*(..))

第一个"*" ---------------- 表示匹配任意返回类型

com.example.druid.controller  --------------  controller的存放包名,需要替换

..  --------------- 当前包以及子包

第二个"*" --------------- 所有类 

第三个"*" ----------------  所有方法

(..)  -----------------   所有类型的参数,如(int a,int b);(int a)


①新建类,在类名上分添加以下注解:

@Aspect
@Component
@Slf4j
@Order(1)

@Aspect 和 @Component 是必须的,@Slf4j 用来打印日志,@Order(1) 设置切面优先级

②定义切入点

在新建的类中新建一个方法,方法名任意取,在方法名上分添加注解如下:

 @Pointcut("execution(public * com.example.druid.controller..*.*(..))")
 //@Pointcut("@annotation(com.example.druid.annotation.Limit)") 也可以这么使用,添加了注解就会调用,括号里面的值是注解的全路径
 public void point(){
}

③在切入点开始处切入内容

新建方法,方法名任意,参数是  (JoinPoint   joinPoint),然后再在方法上添加注解如下: 

@Before("point()") //point换成步骤二中自己取的方法名
public void before(JoinPoint joinPoint){
        // 获取请求域
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();

        // 记录请求内容
        log.info("请求开始时间: "+System.currentTimeMillis());
        log.info("接口路径: " + request.getRequestURI().toLowerCase());
        log.info("请求方式: " + request.getMethod());
        log.info("请求者ip: " + request.getRemoteAddr());
        log.info("请求方法的类名: " + joinPoint.getSignature().getDeclaringTypeName() );
        log.info("请求方法名: "+joinPoint.getSignature().getName());
        log.info("传入的参数: " + Arrays.toString(joinPoint.getArgs()));
}

 获取该注解所在的方法对象:

Method resolveMethod(JoinPoint point) {
		MethodSignature signature = (MethodSignature) point.getSignature();
		Class<?> targetClass = point.getTarget().getClass();
		Method method = getDeclaredMethod(targetClass, signature.getName(), signature.getMethod().getParameterTypes());
		if (method == null) {
			throw new IllegalStateException("无法解析目标方法: " + signature.getMethod().getName());
		}
		return method;
	}
	
	private Method getDeclaredMethod(Class<?> clazz, String name, Class<?>... parameterTypes) {
		try {
			return clazz.getDeclaredMethod(name, parameterTypes);
		} catch (NoSuchMethodException e) {
			Class<?> superClass = clazz.getSuperclass();
			if (superClass != null) {
				return getDeclaredMethod(superClass, name, parameterTypes);
			}
		}
		return null;
	}

@Before 表示,在方法执行前调用,如果你的 controller 中,有参数校验如(@RequestParam(value = "aa",required = true) String aa),若你未传此参数,不会进入方法中,自然不会调用添加了@Before的方法。 

④在切入点结束后切入内容

新建方法,在方法上添加如下注解:

@After("point()") //point换成步骤二中自己的方法名
public void after(){
    log.info("方法结束时间: "+System.currentTimeMillis());
}

@After 表示,在方法执行后调用 

⑤在切入点return内容之后切入内容

新建方法,在方法上添加如下注解:

@AfterReturning(returning = "result", pointcut = "point()")
public void doAfterReturning(Object result) throws Throwable {
		log.info("方法返回值: " + result);
	}

@AfterReturning 表示,在方法返回结果后调用 ,在@After之前执行

returning属性:将返回值用value接收,方法可以打印或处理value值

⑥在切入点发生异常后切入内容

新建方法,在方法上添加如下注解:

@AfterThrowing(pointcut = "point()", throwing = "ex")
	public void afterReturning(JoinPoint point, Exception ex) {
		String methodName = point.getSignature().getName();
		List<Object> args = Arrays.asList(point.getArgs());
		System.out.println("连接点方法为:" + methodName + ",参数为:" + args + ",异常为:" + ex);
	}

@AfterThrowing 表示在切入点发生异常后调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值