在Spring Boot中,利用AOP(Aspect-Oriented Programming)实现操作日志记录。

在Spring Boot中,利用AOP(Aspect-Oriented Programming)结合自定义注解,可以优雅地实现操作日志记录。这种方式不仅解耦了业务逻辑与日志记录功能,还能让代码更简洁、可维护性更高。

以下是实现步骤:

1. 项目依赖

在Spring Boot项目中,确保以下依赖已存在(默认spring-boot-starter-aopspring-boot-starter引入):

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

2. 自定义注解

首先创建一个注解,用于标记需要记录操作日志的方法。

package com.example.aspect;

import java.lang.annotation.*;

@Documented
@Target(ElementType.METHOD) // 作用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时保留
public @interface LogOperation {

    String value() default ""; // 描述信息
}

3. 创建 AOP 切面

通过 AOP 切面拦截带有 @LogOperation 注解的方法,并实现日志记录。

package com.example.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

@Aspect
@Component
public class LogAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    // 定义切点:匹配带有 @LogOperation 注解的方法
    @Pointcut("@annotation(com.example.aspect.LogOperation)")
    public void logPointcut() {
    }

    // 环绕通知:在方法执行前后做增强
    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        // 获取方法信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogOperation logOperation = method.getAnnotation(LogOperation.class);

        // 获取方法参数
        Object[] args = joinPoint.getArgs();

        // 日志内容
        String operationDesc = logOperation.value();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();

        logger.info("开始执行操作: {}", operationDesc);
        logger.info("类名: {}, 方法: {}", className, methodName);
        logger.info("方法参数: {}", Arrays.toString(args));

        Object result;
        try {
            result = joinPoint.proceed(); // 执行目标方法
            logger.info("操作成功: {}", operationDesc);
        } catch (Exception e) {
            logger.error("操作失败: {}, 异常信息: {}", operationDesc, e.getMessage(), e);
            throw e;
        } finally {
            long endTime = System.currentTimeMillis();
            logger.info("操作耗时: {}ms", (endTime - startTime));
        }

        return result;
    }
}

4. 示例:应用注解

在控制器或服务方法中使用 @LogOperation 注解。

控制器示例

package com.example.controller;

import com.example.aspect.LogOperation;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class ExampleController {

    @GetMapping("/example")
    @LogOperation("查询示例数据")
    public String getExample(@RequestParam String name) {
        return "Hello, " + name;
    }

    @PostMapping("/example")
    @LogOperation("保存示例数据")
    public String saveExample(@RequestBody String data) {
        // 模拟保存逻辑
        return "Data saved: " + data;
    }
}

服务层示例

package com.example.service;

import com.example.aspect.LogOperation;
import org.springframework.stereotype.Service;

@Service
public class ExampleService {

    @LogOperation("执行复杂业务逻辑")
    public String complexOperation(String input) {
        // 模拟复杂逻辑
        return "Processed: " + input;
    }
}

5. 日志输出示例

访问 /api/example?name=John 时,日志将输出如下内容:

INFO  - 开始执行操作: 查询示例数据
INFO  - 类名: com.example.controller.ExampleController, 方法: getExample
INFO  - 方法参数: [John]
INFO  - 操作成功: 查询示例数据
INFO  - 操作耗时: 12ms

6. 进阶功能

(1) 保存日志到数据库

可以在 AOP 中直接将日志信息持久化到数据库,例如通过 LogRepository 保存日志:

@Autowired
private LogRepository logRepository;

logRepository.save(new LogEntity(operationDesc, className, methodName, args, timestamp));

(2) 动态获取用户信息

结合 Spring Security 或 Token 解析,获取当前用户信息:

String username = SecurityContextHolder.getContext().getAuthentication().getName();
logger.info("操作用户: {}", username);

(3) 日志级别控制

根据不同操作,选择合适的日志级别(INFO、DEBUG、ERROR 等)。

(4) 异步记录

使用 @Async 注解将日志记录操作改为异步,提高接口响应速度。

7. 完整性测试

对带有 @LogOperation 注解的方法进行测试,验证日志功能是否正常记录,并检查以下场景:

  • 方法执行成功。
  • 方法抛出异常。
  • 方法参数为空。

通过以上实现,利用 AOP 和自定义注解,不仅能优雅地记录操作日志,还能保持业务逻辑的简洁性,为后续功能扩展打下基础。

发布者:myrgd,转载请注明出处:https://www.object-c.cn/4434

Like (0)
Previous 2024年11月23日 下午1:53
Next 2024年11月23日 下午2:03

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

在线咨询: QQ交谈

邮件:723923060@qq.com

关注微信