使用Spring Boot AOP实现日志记录

目录

介绍

[1.1 什么是AOP](#1.1 什么是AOP)

[1.2 AOP体系与概念](#1.2 AOP体系与概念)

AOP简单实现

[2.1 新建一个SpringBoot项目,无需选择依赖](#2.1 新建一个SpringBoot项目,无需选择依赖)

[2.2 设置好本地Maven配置后,在pom.xml文件里添加添加maven依赖](#2.2 设置好本地Maven配置后,在pom.xml文件里添加添加maven依赖)

[2.3 创建一个业务类接口](#2.3 创建一个业务类接口)

[2.4 在实体类实现接口业务](#2.4 在实体类实现接口业务)

[2.5 在单元测试运行结果](#2.5 在单元测试运行结果)

[2.6 创建切面类](#2.6 创建切面类)

[2.7 再次运行测试](#2.7 再次运行测试)

总结


介绍

1.1 什么是AOP

AOP(Aspect Oriented Programming),面向切面思想,是Spring的三大核心思想之一(两外两个:IOC-控制反转、DI-依赖注入)。

那么AOP为何那么重要呢?

在我们的程序中,经常存在一些系统性的需求,比如权限校验、日志记录、统计等,这些代码会散落穿插在各个业务逻辑中,例如下面这个示意图:

有多少业务操作,就要写多少重复的校验和日志记录代码,这显然是无法接受的。当然,用面向对象的思想,我们可以把这些重复的代码抽离出来,写成公共方法,就是下面这样:

这样,代码冗余和可维护性的问题得到了解决,但每个业务方法中依然要依次手动调用这些公共方法,也是略显繁琐。有没有更好的方式呢?有的,为了解决这个问题,面向切面编程(AOP)应运而生。AOP将权限校验、日志记录等非业务代码完全提取出来,与业务代码分离,并寻找节点切入业务代码中:

AOP通过预编译方式和运行动态代理实现程序功能的统一维护,AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各部分进行隔离,是开发人员在编写业务逻辑时,专注核心业务,从而降低业务逻辑各模块之间的耦合度,提高代码重用和开发效率。
AOP使用横向抽取机制,取代纵向集成体系的重复代码建设。使用Aspect,使业务逻辑只关注业务本身,将日志管理、事务处理、性能统计、异常处理、权限控制等代码从业务逻辑代码中抽离,从而实现改变这些行为的时候不影响业务逻辑代码。

1.2 AOP体系与概念


Spring AOP和AspectJ

目前流行的AOP框架分别为Spring AOP和AspectJ。

AOP相关术语


简单地去理解,其实AOP要做三类事:

  • 在哪里切入,也就是权限校验等非业务操作在哪些业务代码中执行。

  • 在什么时候切入,是业务代码执行前还是执行后。

  • 切入后做什么事,比如做权限校验、日志记录等。

因此,AOP的体系可以梳理为下图:

AOP简单实现

下面我们通过一个简单的案例来演示一下AOP的初级应用:

2.1 新建一个SpringBoot项目,无需选择依赖

2.2 设置好本地Maven配置后,在pom.xml文件里添加添加maven依赖

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.3 创建一个业务类接口

如图,建立对应的软件包和接口,并在接口创建方法:

2.4 在实体类实现接口业务

注意,一定要添加Service注解

2.5 在单元测试运行结果

2.6 创建切面类

java 复制代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.StringJoiner;

@Component
@Aspect
public class LogAspect {
    @Before("execution(* com.example.aopdemo.service..*.*(..))")
    public void sysLog(JoinPoint jp){
        StringJoiner log = new StringJoiner("|","{","}");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss");
        log.add(formatter.format(LocalDateTime.now()));

        //当前执行的业务方法名称
        String methodName = jp.getSignature().getName();
        log.add(methodName);

        //方法的参数
        Object[] args = jp.getArgs();
        for(Object arg:args){
            log.add(arg == null ? "-" : arg.toString() );
        }

        System.out.println("AOP日志启动!" + log);
    }

2.7 再次运行测试

再次运行就发发现我们的日志已经添加进去了,并且没有对原代码进行改变,这就是AOP的丝滑之处。

总结

AOP使用横向抽取机制,取代纵向集成体系的重复代码建设。使用Aspect,使业务逻辑只关注业务本身,将日志管理、事务处理、性能统计、异常处理、权限控制等代码从业务逻辑代码中抽离,从而实现改变这些行为的时候不影响业务逻辑代码。实乃开发必备之神器也,本文到此就结束了,希望大家可以有所收获~

相关推荐
这孩子叫逆5 分钟前
Spring Boot项目的创建与使用
java·spring boot·后端
星星法术嗲人8 分钟前
【Java】—— 集合框架:Collections工具类的使用
java·开发语言
黑不溜秋的22 分钟前
C++ 语言特性29 - 协程介绍
开发语言·c++
一丝晨光27 分钟前
C++、Ruby和JavaScript
java·开发语言·javascript·c++·python·c·ruby
天上掉下来个程小白29 分钟前
Stream流的中间方法
java·开发语言·windows
xujinwei_gingko40 分钟前
JAVA基础面试题汇总(持续更新)
java·开发语言
liuyang-neu42 分钟前
力扣 简单 110.平衡二叉树
java·算法·leetcode·深度优先
sp_wxf1 小时前
Lambda表达式
开发语言·python
一丝晨光1 小时前
Java、PHP、ASP、JSP、Kotlin、.NET、Go
java·kotlin·go·php·.net·jsp·asp
罗曼蒂克在消亡1 小时前
2.3MyBatis——插件机制
java·mybatis·源码学习