如果我们想要创建一个自定义注解
,用于记录方法的执行前后日志
,可以通过 AOP
来实现在方法执行前后添加日志记录的逻辑。下面是一个实现的基本步骤
一、自定义注解
- 创建注解
@SysLog
:用于标记要添加日志记录的方法。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) // 作用在方法上
public @interface SysLog {
String value() default "";
// 其他属性...
}
二、定义切面
- 创建日志记录切面
LoggingAspect
:使用 Spring AOP 创建一个切面类,其中包含方法,在方法执行前后记录日志。切面类应该带有@Aspect
注解,并使用@Around
或@Before
和@After
注解来定义日志记录逻辑。
import com.example.vwalkblog.annotation.SysLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Around("@annotation(sysLog)")
public Object logExecution(ProceedingJoinPoint joinPoint, SysLog sysLog) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
log.info("方法开始执行: {}", methodName);
String value = sysLog.value(); // 注解的value值
log.info("注解的value值: {}", value);
Object[] args = joinPoint.getArgs();
// 处理参数...
if (Objects.nonNull(args[0])) {
try {
String jsonStr = JSONObject.toJSONString(args[0]);
log.info("@sysLog 获得方法的第一个参数为: {}", jsonStr);
} catch (Exception e) {
log.error("@sysLog 设置请求参数 {} 异常", args[0]);
}
}
// 执行被注解的方法
Object result = null;
try {
result = joinPoint.proceed();
} catch (Throwable e) {
// 错误记录...
throw new RuntimeException(e);
}finally {
// 返回参数
if (Objects.nonNull(result)) {
// 处理返回值...
log.info("@sysLog 获得方法的返回值为: {}", result);
}
// 将日志入库...
}
log.info("方法执行完成: {}", methodName);
return result;
}
}
在上面的示例中,@Around
注解用于织入日志记录逻辑。它会在被 @SysLog
注解的方法执行前后记录日志。
三、简单例子
- 定义一个类和编写测试单元
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Service
@Slf4j
public class MyService {
@SysLog(value = "Custom log message")
public String drive(String vehicle, String drivingPattern){
log.info("drive() 开...{} 用...{}", vehicle, drivingPattern);
return ("开..." + vehicle + " 用... " + drivingPattern);
}
}
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MyServiceTest {
@Autowired
private MyService myService;
@Test
public void sysLogTest(){
String drive = myService.drive("五菱宏光", "单手");
}
}
别忘了把 @EnableAspectJAutoProxy
添加到启动类。Spring Boot提供了易于使用的默认配置,可以快速启用 AOP。
- 测试结果