SpringBoot中AOP的使用

注解需要的maven坐标:


	org.springframework.boot
	spring-boot-starter-aop

首先需要了解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)") 也可以这么使用,添加了注解就会调用,括号里面的值是注解的全路径
 pubilc 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 = "return", pointcut = "point()")
public void doAfterReturning(Object return) throws Throwable {
		log.info("方法返回值: " + return);
	}

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

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

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

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

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

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

你可能感兴趣的:(积累,java,spring)