springboot使用@Aspect实现AOP记录日志讲解

AOP

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。在日常开发当中经常用来记录日志,方法跟踪、事务,权限等

切面方法说明:

  •  @Aspect -- 作用是把当前类标识为一个切面供容器读取
  • @Pointcut -- (切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
  • @Before -- 标识一个前置增强方法,相当于BeforeAdvice的功能
  • @AfterReturning -- 后置增强,相当于AfterReturningAdvice,方法退出时执行
  • @AfterThrowing -- 异常抛出增强,相当于ThrowsAdvice
  • @After -- final增强,不管是抛出异常或者正常退出都会执行
  • @Around -- 环绕增强,相当于MethodInterceptor 

 

引入AOP依赖

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

定义一个切面--TestAspect

@Aspect
@Component
@Slf4j
public class TestAspect {

    //com.kzj.kzj_rabbitmq.controller 包中所有的类的所有方法切面
    //@Pointcut("execution(public * com.kzj.kzj_rabbitmq.controller.*.*(..))")

    //只针对 MessageController 类切面
    //@Pointcut("execution(public * com.kzj.kzj_rabbitmq.controller.MessageController.*(..))")

    //统一切点,对com.kzj.kzj_rabbitmq.controller及其子包中所有的类的所有方法切面
    @Pointcut("execution(public * com.kzj.kzj_rabbitmq.controller..*.*(..))")
    public void Pointcut() {
    }

    //前置通知
    @Before("Pointcut()")
    public void beforeMethod(JoinPoint joinPoint){
        log.info("调用了前置通知");

    }

    //@After: 后置通知
    @After("Pointcut()")
    public void afterMethod(JoinPoint joinPoint){
        log.info("调用了后置通知");
    }
    //@AfterRunning: 返回通知 rsult为返回内容
    @AfterReturning(value="Pointcut()",returning="result")
    public void afterReturningMethod(JoinPoint joinPoint,Object result){
        log.info("调用了返回通知");
    }
    //@AfterThrowing: 异常通知
    @AfterThrowing(value="Pointcut()",throwing="e")
    public void afterReturningMethod(JoinPoint joinPoint, Exception e){
        log.info("调用了异常通知");
    }

    //@Around:环绕通知
    @Around("Pointcut()")
    public Object Around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("around执行方法之前");
        Object object = pjp.proceed();
        log.info("around执行方法之后--返回值:" +object);
        return object;
    }

}

添加测试用Controller

@RestController
@Slf4j
public class MessageController {

    @RequestMapping(value="/send_message",produces = "text/json;charset=UTF-8")
    public String send_message(MessagePojo pojo) throws Exception {
        log.info("执行了controller.send_message方法");
        return JSON.toJSONString(pojo);
    }
}

测试:

在浏览器输入:http://localhost:9999/send_message?delay=15&className=B

可看到打印

可以看到,aspect类内部的 advice 将按照以下的顺序进行执行

one-ok

下面是项目中实战-使用AOP打印日志和效率监听(记录请求参数和返回结果和方法运行总时间)

@Aspect
@Component
@Slf4j
public class TestAspect {

    //com.kzj.kzj_rabbitmq.controller 包中所有的类的所有方法切面
    //@Pointcut("execution(public * com.kzj.kzj_rabbitmq.controller.*.*(..))")

    //只针对 MessageController 类切面
    //@Pointcut("execution(public * com.kzj.kzj_rabbitmq.controller.MessageController.*(..))")

    //统一切点,对com.kzj.kzj_rabbitmq.controller及其子包中所有的类的所有方法切面
    @Pointcut("execution(public * com.kzj.kzj_rabbitmq.controller..*.*(..))")
    public void Pointcut() {
    }


    //@Around:环绕通知
    @Around("Pointcut()")
    public Object Around(ProceedingJoinPoint pjp) throws Throwable {
        Map<String,Object> data = new HashMap<>();
        //获取目标类名称
        String clazzName = pjp.getTarget().getClass().getName();
        //获取目标类方法名称
        String methodName = pjp.getSignature().getName();

        //记录类名称
        data.put("clazzName",clazzName);
        //记录对应方法名称
        data.put("methodName",methodName);
        //记录请求参数
        data.put("params",pjp.getArgs());
        //开始调用时间
        // 计时并调用目标函数
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();
        Long time = System.currentTimeMillis() - start;

        //记录返回参数
        data.put("result",result);

        //设置消耗总时间
        data.put("consumeTime",time);
        System.out.println(data);
        return result;

    }

}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值