以前写过很多次Aop切面,基于xml的配置方式,最近要求对每个接口进行权限校验,而不是页面,因为无法避免某个人没有页面权限,但是知道接口的情况,也刚好整理一下。
1.引入依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
|
2.编写LogAspect类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| /** * @author zllwsy * @Description * @Date 2021/7/28 13:48 * @Created by zllwsy */ @Component @Aspect public class LogAspect { //切入点表达式 @Pointcut("execution(* com.zl.aop.controller.*.*(..))") public void aopCut(){
}
//前置通知,也就是在目标方法执行之前执行 @Before(value = "aopCut()") public void before(JoinPoint joinPoint){ //获取目标方法的名称 String name = joinPoint.getSignature().getName(); System.out.println(name + "方法执行之前"); }
//后置通知,也就是方法执行之后,获取目标方法的返回值 @AfterReturning(value = "aopCut()",returning = "result") public void afterReturning(JoinPoint joinPoint,Object result){ String name = joinPoint.getSignature().getName(); System.out.println(name + "方法执行之后," + ", 返回值为: " + result); }
//异常通知,也就是当方法出现异常时,调用该方法 @AfterThrowing(value = "aopCut()",throwing = "e") public void afterThrowing(JoinPoint joinPoint,Exception e){ String name = joinPoint.getSignature().getName(); System.out.println(name + "方法执行之后," + "抛出异常: " + e); }
//环绕通知,也就是可实现任意通知,可调用 proceedingJoinPoint.proceed() 方法使目标方法继续执行 @Around(value = "aopCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { String name = joinPoint.getSignature().getName(); //获取方法传入的参数 Object[] args = joinPoint.getArgs(); //可在这里对方法进行处理,调用自定义注解 ZLAopCut declaredAnnotation = getDeclaredAnnotation(joinPoint); //然后调用proceed继续执行方法 Object proceed = joinPoint.proceed(); System.out.println("around"); return proceed; }
//自定义注解 public ZLAopCut getDeclaredAnnotation(ProceedingJoinPoint joinPoint)throws NoSuchMethodException { // 获取方法名 String methodName = joinPoint.getSignature().getName(); // 反射获取目标类 Class<?> targetClass = joinPoint.getTarget().getClass(); // 拿到方法对应的参数类型 Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes(); // 根据类、方法、参数类型(重载)获取到方法的具体信息 Method objMethod = targetClass.getMethod(methodName, parameterTypes); // 拿到方法定义的注解信息 ZLAopCut annotation = objMethod.getDeclaredAnnotation(ZLAopCut.class); // 返回 return annotation; } }
|
3.编写自定义注解
1 2 3 4 5 6 7 8 9 10 11
| /** * @author zllwsy * @Description * @Date 2021/7/28 14:08 * @Created by zllwsy */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ZLAopCut { String method(); }
|
4.编写controller
1 2 3 4 5 6 7 8 9 10 11 12 13
| /** * @Description * @Date 2021/7/28 14:12 * @Created by zllwsy */ @RestController @RequestMapping("/aop") public class AopController { @GetMapping("/test") public String test() { return "执行aop"; } }
|
5.执行结果
6.总结
可适当根据自己的需求决定要加入哪些部分,自定义注解配合Around能够灵活的做一些操作,比如权限校验,接口权限等等。