Springboot自定义注解
在Spring Boot项目中,通过自定义注解和AOP实现方法执行前后的日志记录,可以按照以下步骤操作:
步骤 1:添加依赖
确保pom.xml
中包含AOP依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
步骤 2:创建自定义注解
定义@Loggable
注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
}
步骤 3:实现AOP切面
创建切面类处理日志逻辑:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Aspect
@Component
public class LoggingAspect {
private final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
private final ObjectMapper objectMapper = new ObjectMapper();
@Around("@annotation(Loggable)")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String className = signature.getDeclaringType().getSimpleName();
String methodName = signature.getName();
Object[] args = joinPoint.getArgs();
// 记录方法入参
logger.info(">>> 方法 {}.{} 入参: {}", className, methodName, Arrays.toString(args));
try {
long startTime = System.currentTimeMillis();
// 执行目标方法
Object result = joinPoint.proceed();
long elapsedTime = System.currentTimeMillis() - startTime;
// 记录返回结果和执行时间
logger.info("<<< 方法 {}.{} 耗时: {} ms, 返回值: {}",
className,
methodName,
elapsedTime,
objectMapper.writeValueAsString(result));
return result;
} catch (Throwable e) {
// 记录异常信息
logger.error("!!! 方法 {}.{} 异常: {}", className, methodName, e.getMessage(), e);
throw e;
}
}
}
步骤 4:使用注解
在需要监控的方法上添加@Loggable
:
@RestController
@RequestMapping("/api/aop")
public class AopController {
@GetMapping("getResult/{param}")
@Loggable
public ResponseEntity<String> getResult(@PathVariable("param") String param){
return new ResponseEntity<>("12345678", HttpStatus.OK);
}
}
高级配置建议
- 敏感信息过滤:在序列化前排除敏感字段。
- 性能优化:添加条件判断,仅在调试模式记录完整日志。
- 异步日志:使用异步Appender提升性能。
- 自定义序列化:对特定类型定制序列化方式。
执行效果示例
2025-03-06 22:39:36.646 INFO 5268 --- [nio-8080-exec-3] com.sh.system.config.LoggingAspect : >>> 方法 AopController.getResult 入参: [123]
2025-03-06 22:39:36.659 INFO 5268 --- [nio-8080-exec-3] com.sh.system.config.LoggingAspect : <<< 方法 AopController.getResult 耗时: 2 ms, 返回值: {"headers":{},"body":"12345678","statusCode":"OK","statusCodeValue":200}
接口调用
注意事项
- 确保Spring Boot版本 ≥ 2.x
- 复杂对象需实现
toString()
或配置Jackson序列化 - 内部方法调用需通过代理对象执行
以上实现会完整记录方法执行的输入参数、返回结果和执行耗时,异常时会记录堆栈跟踪信息。