IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot AOP学习(二):Spring AOP实现日志功能 -> 正文阅读

[Java知识库]SpringBoot AOP学习(二):Spring AOP实现日志功能

前言

感谢阅读菜菜的文章,本篇文章是继上一篇 SpringBoot AOP学习(一):AOP的诞生及AOP注解介绍后对AOP注解的使用作一个具体的应用,由于本身我也是才接触不久,借此机会把自己的学习心得记录下来,也希望各位大佬不吝赐教~
在这里插入图片描述
为了学起来更加得心应手,这里简单复习了下IOC:

IOC理论,用来实现对象之间的“解耦”,解决对象之间的耦合度过高的问题。IOC(控制反转)的具体实现是通过借助于“第三方”实现具有依赖关系的对象之间的解耦,这个“第三方”就是IOC容器;同时,IOC也叫依赖注入(DI),那么这两种叫法的区别是什么,且看:
控制反转:获得依赖对象的过程被反转了,从前主动,现在被动
依赖注入:就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中
他们两兄弟是同一个东西从不同的角度来进行描述的,IOC中最基本的技术就是“反射(Reflection)”编程

AOP日志功能实战

菜菜接触一个项目要实现日志功能,需求如下:

1、记录操作人、操作时间
2、记录request请求参数
3、记录response回调数据
4、记录具体的业务描述供系统使用者查看(这里需要自定义注解)
在这里插入图片描述

案例代码结构

为了方便,菜菜将所有代码放在了同一包内
在这里插入图片描述

重点就是这个Aspect切面类
开始实现
首先,
在这里插入图片描述
先定义实体类和controller类

ReqDTO.java

package com.caicai.aop.csdn;


import lombok.Data;

@Data
public class ReqDTO {

    private String user_id;

    private String user_name;
}

TestController.java

package com.caicai.aop.csdn;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/aop")
public class TestController {

        @RequestMapping(path = "/test", method = RequestMethod.POST)
        @MyLog(operateType = "Log测试", operateExplain = "模拟日志记录")  //这里使用的自定义注解
        public String test(@RequestBody ReqDTO reqDTO) {
//            int i = 1 / 0;   //模拟异常
            System.out.println("调用 Log测试 方法");
            return "调用 Log测试 方法 end" ;
        }
    }

然后是定义自定义注解

MyLog .java

package com.caicai.aop.csdn;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public  @interface MyLog {
    /** 操作类型 **/
    String operateType();
    /** 操作解释 **/
    String operateExplain();
}

最后,定义我们的切面
在这里插入图片描述

要想把一个类变成切面类,需要两步,

第一步,在类上使用 @Component 注解 把切面类加入到IOC容器中
第二步,在类上使用 @Aspect 注解 使之成为切面类

TestAspect .java

package com.caicai.aop.csdn;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @Aspect 切面类注解实例
 * @author 菜菜bu菜
 */


//声明这是一个组件
@Component
//声明这是一个切面Bean
@Aspect
public class TestAspect {


    //配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
    //@annotation表示标注了某个注解的所有方法
    @Pointcut("@annotation(com.caicai.aop.csdn.MyLog)")
    public void aspect(){   }


    //配置前置通知,使用在方法aspect()上注册的切入点
    //同时接受JoinPoint切入点对象,可以没有该参数
  
    @Before("aspect()")
    public void Before(){
        System.out.println("---------Before方法开始执行");
    }

    //配置后置通知,使用在方法aspect()上注册的切入点
    @After("aspect()")
    public void After(JoinPoint joinPoint){
        System.out.println("---------After方法开始执行");
    }

    //最终通知
    //returning能够将目标方法的返回值传到切面增强方法里
    //声明rvt时指定的类型会限制目标方法必须返回指定类型(String)的值或没有返回值
    //此处将rvt的类型声明为Object,意味着对目标方法的返回值不加限制
    @AfterReturning(pointcut ="aspect()",returning = "rvt")
    public void AfterReturning(String rvt){
        System.out.println("--------AfterReturning方法开始执行:---"+rvt);
    }

    //异常通知
    //声明e时指定的类型会限制目标方法必须抛出指定类型的异常
    //此处将e的类型声明为Throwable,意味着对目标方法抛出的异常不加限制
    @AfterThrowing(pointcut="aspect()",throwing="e")
    public void AfterThrowing(Throwable e){
        System.out.println("--------AfterThrowing方法开始执行:"+e);
    }


    //@Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务。
    //功能很强大,可以深入了解下
    @Around("aspect()")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("--------Around方法开始执行");
        //获取自定义注解里面的值
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();
        MyLog logAnnotation = (MyLog)method.getAnnotation(MyLog.class);
        System.err.println("operateType:------"+logAnnotation.operateType());
        System.err.println("operateExplain:------"+logAnnotation.operateExplain());

        //获取入参
        Object[] objs = joinPoint.getArgs();
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 参数名
        Map<String, Object> paramMap = new HashMap<String, Object>();
        for (int i = 0; i < objs.length; i++) {
            paramMap.put(argNames[i], objs[i]);
        }
        System.err.println("入参:"+paramMap.toString());

        //获取出参
        Object result =joinPoint.proceed();
        System.err.println("出参:"+result.toString());
        return result;

    }

}

测试

正常测试

在这里插入图片描述
结果:

--------Around方法开始执行
---------Before方法开始执行
调用 Log测试 方法
--------AfterReturning方法开始执行:---调用 Log测试 方法 end
---------After方法开始执行
operateType:------Log测试
operateExplain:------模拟日志记录
入参:{reqDTO=ReqDTO(user_id=1234, user_name=3423)}
出参:调用 Log测试 方法 end

异常测试

在TestController.java下test方法里面加上 int i = 1 / 0; //模拟异常

  @RequestMapping(path = "/test", method = RequestMethod.POST)
        @MyLog(operateType = "Log测试:", operateExplain = "模拟日志记录")  //这里使用的自定义注解
        public String test(@RequestBody  ReqDTO reqDTO) {
            int i = 1 / 0;   //模拟异常
            System.out.println("调用 Log测试 方法");
            return "调用 Log测试 方法 end" ;
        }

再次发送请求
在这里插入图片描述
结果:

--------Around方法开始执行
---------Before方法开始执行
--------AfterThrowing方法开始执行:java.lang.ArithmeticException: / by zero
---------After方法开始执行
operateType:------Log测试
operateExplain:------模拟日志记录
入参:{reqDTO=ReqDTO(user_id=1234, user_name=3423)}

总结

AOP真真真强啊!面向切面编程(aop)是对面向对象编程(oop)的补充,面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。

实现AOP的技术,主要分为两大类

  1. 采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
  2. 采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码,属于静态代理。

AOP框架具有的两个特征

  1. 各个步骤之间的良好隔离性
  2. 源代码无关性

AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象。
在这里插入图片描述
最后,对于实际应用中 @Around的应用非常广泛,下一篇来具体学习一下它~

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:31:00  更:2021-08-23 16:31:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:18:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码