SpringBoot学习笔记——aop
它是一种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想。用于切入到指定类指定方法的代码片段叫做切面,而切入到哪些类中的哪些方法叫做切入点
AOP编程允许把遍布应用各处的功能分离出来形成可重用的组件
实现一个AOP可以分成下面几个步骤:
1.引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.自定义注解 @Permission,其中的 @Target 和 @Retention 元注解参考:元注解(Annotation)
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Permission { }
参考
3.编写切点
常用的Aspect指示器:@execution,@within,@annotation
@execution:用于在方法执行时触发,如:在com.example.demo.controller.XXXController.register方法在任意参数(..)下执行,返回任意类型(*)的情况下执行
@Pointcut("execution(* com.example.demo.controller.XXXController.register(..))")
@within:用于在方法执行时触发,如:在com.example.demo.controller包下的任意方法执行
@Pointcut("within(com.example.demo.controller.*)")
@annotation:用于注解对象,如:指定 com.example.xxx 包下及其所有子目录下的所有带有 @hello 注解的方法体为切点
@Pointcut("within(com.example.xxx.*) && @annotation(hello)")
4.编写切点checkTokenCut,以及定义切面Aspect,简单检查request请求的cookie中是否包含token,且切点设置在添加了 @Permission 注解的 方法上
此外还可以在aop类上添加 @Order注解,来定义Spring IOC容器中Bean的执行顺序的优先级,值越小拥有越高的优先级,可为负数
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @Slf4j @Aspect @Component public class PermissionAspect { @Pointcut("@annotation(com.example.demo.annotation.Permission) && within(com.example.demo.controller.*)") public void checkTokenCut() { } @Around("checkTokenCut()") public Object doCheckToken(ProceedingJoinPoint point) throws Throwable { ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = attr.getRequest(); Cookie[] cookies = request.getCookies(); int len = cookies.length; for (int i = 0; i < len; i++) { Cookie cookie = cookies[i]; if ("token".equals(cookie.getName())) { log.info("has token"); break; } if (i == len - 1) { log.info("no token"); } } //执行代理目标方法 return point.proceed(); } }
5.注入AspectJ切面 @Permission
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @RequestMapping(path = "/fail", method = RequestMethod.GET) @Permission public ControllerResponseT fail() { return ControllerResponseT.ofFail(50001, "error", null); }
请求接口的时候将会执行check token逻辑
参考:SpringBoot使用AOP+注解实现简单的权限验证
其他aop的例子:
使用aop实现数据脱敏:改造了以前写的数据脱敏插件,更好用了
使用aop实现接口响应时间记录:Spring Boot 2实践系列(四十七):Spring AOP 实现API接口处理请求耗时监控
使用aop实现全局异常处理以及统一打印接口请求入参和返回结果日志,打印接口访问性能日志,处理sql注入攻击以及处理入参特殊字符等问题:Springboot项目全局异常统一处理
本文只发表于博客园和tonglin0325的博客,作者:tonglin0325,转载请注明原文链接:https://www.cnblogs.com/tonglin0325/p/5312436.html