面向切面编程-AOP

发布于:2023-10-25 ⋅ 阅读:(100) ⋅ 点赞:(0)

一.什么是AOP?

AOP称为面向切面编程,用于将那些与业务无关,但又对多个对象产生公共行为影响的代码,抽取并封装成一个可用的模块,这个模块被命名为切面。

二.AOP的作用和常用场景

作用:减少重复代码,降低模块之间的耦合程度,同时提高了系统的可维护性

常用场景:1.记录操作日志

                  2.缓存处理

                  3.spring内置的事务处理

三.使用方法

1.添加依赖

<!--        Aop-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.添加@Conponent和@Aspect注解

//统计调用方法的使用时间
@Slf4j
@Component
@Aspect //AOP类
public class TimeAspect {
    @Around("execution(* com.itheima.service.*.*(..))")  //切入点表达式
   public  Object  recordTime(ProceedingJoinPoint joinPoint) throws Throwable {

       //1.记录开始时间
       long begin=System.currentTimeMillis();

       //2.调用原始方法运行
       Object result=joinPoint.proceed();
       //3.记录结束时间,计算执行耗时
       long end=System.currentTimeMillis();
       log.info(joinPoint.getSignature()+ "方法执行耗时:{}ms",end-begin);


       return result;
   }

}

3.通知类型(5种类型)

我们常用的就是@Around类型通知,

@Pointcut:该注解的作用是将公共的切点表达式抽取出来,需要到时引用该切点表达式即可

//切点,指定重复的切入点表达式,引用时,引用所属的方法即可,如@Around("pt()")

如:

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

4.通知顺序

//系统默认

@before:类名字母排序越靠前越先执行

@after:类名字母排序越靠后越先执行

//可以用@Order注解给每一个通知加上优先级,指定数字

如@Order(5)

@before:数字小的先执行

@after:数字大的先执行

5.切点表达式

作用:主要是用来决定项目中的哪些方法需要加入通知

常见形式:1.execution(.....) 根据方法的签名来匹配

                   2.@annotation(....):根据注解匹配

//如果要执行两个切点表达式可以用逻辑运算符与或非进行判断

@Pointcut("execution(* com.itheima.service.DeptService.list()) || " +
        "execution(* com.itheima.service.DeptService.delete(java.lang.Integer))")

@Annotation

1.先自己创建一个注解,如Mylog

package com.wpk.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
}

2.在自己想通知的实现方法上添加上,自己创建的注解,如@Mylog,一般放在Controller方法上

3.引用切点表达式,如Around("@annotation(com.itheima.aop.Mylog)")

6.连接点

7.AOP案例

1.创建数据库文件

2.创建数据库文件对应的实体类

3.创建自定义注解,并在Controller方法上添加注解

4.定义Mapper往数据库添加信息

5.创建aop切面类,如下面所示

package com.wpk.aop;

import com.alibaba.fastjson.JSONObject;
import com.wpk.mapper.OperateLogMapper;
import com.wpk.pojo.OperateLog;
import com.wpk.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Component
@Aspect
public class LogAspect {
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private OperateLogMapper operateLogMapper;
    @Around("@annotation(com.wpk.anno.Log)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        //操作人ID
        String jwt = request.getHeader("token");
        Claims claims=JwtUtils.parseJWT(jwt);
        Integer operateUser=(Integer) claims.get("id");
        //操作时间
        LocalDateTime operatTime=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();
        //1.调用原始目标方法运行
        Object result=joinPoint.proceed();
        //方法返回值
        String returnValue=JSONObject.toJSONString(result);
        //结束时间
        Long end=System.currentTimeMillis();
        //操作耗时
        Long costTime=end-begin;

        //2.记录操作日志
        OperateLog operateLog=new OperateLog(null,operateUser,operatTime,className,methodName,methodParams,returnValue,costTime);
        operateLogMapper.insert(operateLog);
        return  result;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到