Springboot AOP介绍及实战

介绍

AOP是Aspect Oriented Program的首字母缩写;这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

主要用于非核心业务处理,比如权限,日志记录、异常处理,性能监控等。

详细请看:https://www.zhihu.com/question/24863332

实战

此处就实现一个日志记录的例子。

自定义注解

@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface OperLog {
    String operModule() default ""; // 操作模块
    String operType() default "";  // 操作类型
    String operDesc() default "";  // 操作说明
}

创建aspect

@Slf4j
@Aspect
@Component
public class OperLogAspect {
    /**
     * 操作日志切入点
     */
    @Pointcut("@annotation(com.sgtech.java.aop.annotation.OperLog)")
    public void operLogPoinCut() {
    }

    @Before("operLogPoinCut()") //在切入点的方法run之前要干的
    public void logBeforeController(JoinPoint joinPoint) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();

        log.info("################请求路径 : " + request.getRequestURL().toString());
        log.info("################请求方式 : " + request.getMethod());
        log.info("################客户端IP : " + request.getRemoteAddr());
        log.info("################方法参数: " + Arrays.toString(joinPoint.getArgs()));

        //下面这个getSignature().getDeclaringTypeName()是获取包+类名的   然后后面的joinPoint.getSignature.getName()获取了方法名
        log.info("################执行方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        //logger.info("################TARGET: " + joinPoint.getTarget());//返回的是需要加强的目标类的对象
        //logger.info("################THIS: " + joinPoint.getThis());//返回的是经过加强后的代理类的对象

    }

    @Around("operLogPoinCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取操作
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        // 获取切入点所在的方法
        Method callMethod = signature.getMethod();
        OperLog opLog = callMethod.getAnnotation(OperLog.class);

        if(opLog != null){
            log.info("请求的系统操作:{}-{}-{}",opLog.operModule(),opLog.operType(),opLog.operDesc());
        }

        Object proceed = pjp.proceed(); //执行目标方法
        return proceed; //返回目标方法执行结果
    }

}

创建业务类

/**
 * @Description: 模拟用户增删改查接口
 * @Author laoxu
 * @Date 2021-10-19 15:18
 **/
@RestController
@RequestMapping("/user")
public class UserController {
    @OperLog(operModule = "系统管理",operType = "新增",operDesc = "新增用户")
    @GetMapping("/add")
    public String add(){
        return "新增用户";
    }
    @OperLog(operModule = "系统管理",operType = "修改",operDesc = "修改用户")
    @GetMapping("/modify")
    public String modify(){
        return "修改用户";
    }
    @OperLog(operModule = "系统管理",operType = "查询",operDesc = "查询用户")
    @GetMapping("/list")
    public String list(){
        return "查询用户";
    }
    @OperLog(operModule = "系统管理",operType = "删除",operDesc = "删除用户")
    @GetMapping("/remove")
    public String remove(){
        return "删除用户";
    }
}

测试

在这里插入图片描述
在这里插入图片描述

源码下载

https://gitee.com/indexman/spring_boot_in_action

posted @ 2021-10-19 17:37  一锤子技术员  阅读(10)  评论(0编辑  收藏  举报  来源