SpringBootWeb AOP

发布于:2024-10-10 ⋅ 阅读:(14) ⋅ 点赞:(0)

SpringBootWeb AOP

事务管理

rollbackFor属性

propagation属性

 案例

AOP

基础

 进阶

通知类型

通知顺序

 切入点表达式

execution

@annotation

连接点

案例

实体类

接口方法

切面类


事务管理

rollbackFor属性

propagation属性

REQUIRED:大部分情况下都是用该传播行为即可。
REOUIRES_NEW:当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。

 案例

Grep Console插件可用于日志过滤筛选

AOP

基础

 进阶

通知类型

@Slf4j
@Component
@Aspect
public class MyAspect1 {

    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public void pt() {
    }

    @Before("pt()")
    public void before() {
        log.info("before ...");
    }

    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before ...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();

        log.info("around after ...");
        return result;
    }

    @After("pt()")
    public void after() {
        log.info("after ...");
    }

    @AfterReturning("pt()")
    public void afterReturning() {
        log.info("afterReturning ...");
    }

    @AfterThrowing("pt()")
    public void afterThrowing() {
        log.info("afterThrowing ...");
    }
}

通知顺序

 切入点表达式

execution

//切面类
@Slf4j
@Aspect
@Component
public class MyAspect6 {

    //@Pointcut("execution(public void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    //@Pointcut("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    //@Pointcut("execution(void delete(java.lang.Integer))") //包名.类名不建议省略
    //@Pointcut("execution(void com.itheima.service.DeptService.delete(java.lang.Integer))")

    //@Pointcut("execution(void com.itheima.service.DeptService.*(java.lang.Integer))")
    //@Pointcut("execution(* com.*.service.DeptService.*(*))")
    //@Pointcut("execution(* com.itheima.service.*Service.delete*(*))")

    //@Pointcut("execution(* com.itheima.service.DeptService.*(..))")
    //@Pointcut("execution(* com..DeptService.*(..))")
    //@Pointcut("execution(* com..*.*(..))")
    //@Pointcut("execution(* *(..))") //慎用

    @Pointcut("execution(* com.itheima.service.DeptService.list()) || " +
            "execution(* com.itheima.service.DeptService.delete(java.lang.Integer))")
    private void pt(){}

    @Before("pt()")
    public void before(){
        log.info("MyAspect6 ... before ...");
    }

}
@annotation

@annotation 切入点表达式,用于匹配标识有特定注解的方法。

连接点

在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。

对于 @Around 通知,获取连接点信息只能使用 ProceedingJoinPoint

对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint 的父类型

//切面类
@Slf4j
@Aspect
@Component
public class MyAspect8 {

    @Pointcut("execution(* com.itheima.service.DeptService.*(..))")
    private void pt(){}

    @Before("pt()")
    public void before(JoinPoint joinPoint){
        log.info("MyAspect8 ... before ...");
    }

    @Around("pt()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("MyAspect8 around before ...");

        //1. 获取 目标对象的类名 .
        String className = joinPoint.getTarget().getClass().getName();
        log.info("目标对象的类名:{}", className);

        //2. 获取 目标方法的方法名 .
        String methodName = joinPoint.getSignature().getName();
        log.info("目标方法的方法名: {}",methodName);

        //3. 获取 目标方法运行时传入的参数 .
        Object[] args = joinPoint.getArgs();
        log.info("目标方法运行时传入的参数: {}", Arrays.toString(args));

        //4. 放行 目标方法执行 .
        Object result = joinPoint.proceed();

        //5. 获取 目标方法运行的返回值 .
        log.info("目标方法运行的返回值: {}",result);

        log.info("MyAspect8 around after ...");
        return result;
    }
}

案例

步骤
准备:
在案例工程中引入AOP的起步依赖
导入资料中准备好的数据库表结构,并引入对应的实体类
编码:
自定义注解 @Log
定义切面类,完成记录操作日志的逻辑
获取当前登录用户
获取request对象,从请求头中获取到jwt令牌,解析令牌获取出当前用户的id。

实体类

接口方法

切面类

@Slf4j
@Aspect
@Component
public class LogAspect {
    @Autowired
    private OperateLogMapper operateLogMapper;

    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(com.itheima.anno.Log)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        Integer operateUser = (Integer)claims.get("id");
        LocalDateTime operateTime= LocalDateTime.now();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String methodParams = Arrays.toString(args);
        long begin = System.currentTimeMillis();
        Object result=joinPoint.proceed();
        long end = System.currentTimeMillis();
        String returnValue = JSONObject.toJSONString(result);
        Long costTime = end - begin;
        OperateLog oprateLog= new OperateLog(null,operateUser,operateTime,className,methodName,methodParams,returnValue,costTime);
        operateLogMapper.insert(oprateLog);
        log.info("aop记录日志成功{}",oprateLog);
        return result;
    }
}