下面是详解 SpringBoot AOP 拦截器(Aspect 注解方式)的完整攻略,并附带两条示例。
什么是 AOP
AOP(Aspect Oriented Programming,面向切面编程)是一种面向对象编程的编程思想,AOP 的思想是将系统分解为多个功能单元,称之为“切面”(Aspect),然后编写代码来定义这些切面。这些切面可以跨越多个类,不仅仅是某个类的某个方法。AOP 主要用于解决系统中的横切关注点(Crosscutting Concerns)问题,比如日志记录、性能统计、安全控制、事务处理等。
什么是 SpringBoot AOP 拦截器(Aspect 注解方式)
SpringBoot AOP 在 AOP 基础上,采用了拦截器的方式来实现对方法的切面编程。SpringBoot AOP 拦截器可以根据注解设置来实现不同的切面,常见的切面有:
- @Before:在方法之前执行。
- @After:在方法之后执行。
- @AfterReturning:在方法正常返回之后执行。
- @AfterThrowing:在方法抛出异常之后执行。
SpringBoot AOP 拦截器(Aspect 注解方式)的实现步骤
下面是 SpringBoot AOP 拦截器(Aspect 注解方式)的实现步骤:
步骤一:创建一个自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}
步骤二:编写 AOP 切面代码
@Aspect
@Component
@Slf4j
public class LogAspect {
@Around("@annotation(com.example.demo.annotation.Log)")
public Object logRecord(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result = null;
try {
// 方法执行前
String className = proceedingJoinPoint.getTarget().getClass().getName();
String methodName = proceedingJoinPoint.getSignature().getName();
log.info("Class Name: {}, Method Name:{}", className, methodName);
Object[] args = proceedingJoinPoint.getArgs();
for (Object arg : args) {
log.info("Args: {}", arg);
}
result = proceedingJoinPoint.proceed(args);
// 方法正常返回
log.info("Result:{}", result);
} catch (Throwable throwable) {
// 方法执行异常
log.error("Method Execution Error:{}", throwable.getMessage());
throw throwable;
}
return result;
}
}
步骤三:在需要切面的方法上添加自定义注解
@RestController
public class UserController {
@Autowired
private UserService userService;
@Log(value = "查询用户信息")
@GetMapping("/user/get/{id}")
public UserVO getUserById(@PathVariable("id") Long id) {
return userService.getUserById(id);
}
}
示例一:记录用户操作日志
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserOperateLog {
String value() default "";
}
@Aspect
@Component
@Slf4j
public class UserOperateLogAspect {
@Autowired
private UserOperateLogService userOperateLogService;
@Around("@annotation(com.example.demo.annotation.UserOperateLog)")
public Object userOperateLogRecord(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result = null;
try {
// 方法执行前
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
UserOperateLog userOperateLogAnn = signature.getMethod().getAnnotation(UserOperateLog.class);
String operation = userOperateLogAnn.value();
String className = proceedingJoinPoint.getTarget().getClass().getName();
String methodName = proceedingJoinPoint.getSignature().getName();
log.info("Class Name: {}, Method Name:{}, Operation: {}", className, methodName, operation);
// 记录用户操作日志
User user = SessionUtils.getCurrentUser();
if (user != null) {
UserOperateLog userOperateLog = new UserOperateLog();
userOperateLog.setUserId(user.getId());
userOperateLog.setUserName(user.getName());
userOperateLog.setOperation(operation);
userOperateLog.setOperateTime(new Date());
userOperateLogService.saveUserOperateLog(userOperateLog);
}
Object[] args = proceedingJoinPoint.getArgs();
result = proceedingJoinPoint.proceed(args);
// 方法正常返回
log.info("Result:{}", result);
} catch (Throwable throwable) {
// 方法执行异常
log.error("Method Execution Error:{}", throwable.getMessage());
throw throwable;
}
return result;
}
}
@RestController
public class UserController {
@Autowired
private UserService userService;
@UserOperateLog(value = "查询用户信息")
@GetMapping("/user/get/{id}")
public UserVO getUserById(@PathVariable("id") Long id) {
return userService.getUserById(id);
}
}
示例二:时间统计
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeCount {
String value() default "";
}
@Aspect
@Component
@Slf4j
public class TimeCountAspect {
@Around("@annotation(com.example.demo.annotation.TimeCount)")
public Object timeCount(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result = null;
try {
// 方法执行前
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
TimeCount timeCountAnn = signature.getMethod().getAnnotation(TimeCount.class);
String operation = timeCountAnn.value();
long startTime = System.currentTimeMillis();
result = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
log.info("Operation: {},TimeCost: {}ms", operation, endTime - startTime);
} catch (Throwable throwable) {
// 方法执行异常
log.error("Method Execution Error:{}", throwable.getMessage());
throw throwable;
}
return result;
}
}
@RestController
public class UserController {
@Autowired
private UserService userService;
@TimeCount(value = "查询用户信息")
@GetMapping("/user/get/{id}")
public UserVO getUserById(@PathVariable("id") Long id) {
return userService.getUserById(id);
}
}
以上就是详解 SpringBoot AOP 拦截器(Aspect 注解方式)的完整攻略以及两条示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解SpringBoot AOP 拦截器(Aspect注解方式) - Python技术站