本文目录导读:

在Java AOP中,控制切面(Aspect)的执行顺序是一个常见需求,我会通过几种不同的方式来说明如何控制切面顺序。
使用 @Order 注解(最常用)
示例代码
// 第一个切面 - 权限校验
@Aspect
@Component
@Order(1) // 数值越小,优先级越高,越先执行
public class PermissionAspect {
@Around("@annotation(permissionCheck)")
public Object checkPermission(ProceedingJoinPoint joinPoint, PermissionCheck permissionCheck) throws Throwable {
System.out.println("【权限切面】开始执行 - Order 1");
// 模拟权限校验
String permission = permissionCheck.value();
System.out.println("检查权限: " + permission);
Object result = joinPoint.proceed();
System.out.println("【权限切面】执行结束");
return result;
}
}
// 第二个切面 - 日志记录
@Aspect
@Component
@Order(2) // 数值较大,优先级较低,后执行
public class LogAspect {
@Around("@annotation(LogRecord)")
public Object logAround(ProceedingJoinPoint joinPoint, LogRecord logRecord) throws Throwable {
System.out.println("【日志切面】开始执行 - Order 2");
System.out.println("记录日志: " + logRecord.value());
Object result = joinPoint.proceed();
System.out.println("【日志切面】执行结束");
return result;
}
}
// 第三个切面 - 事务管理
@Aspect
@Component
@Order(3) // 数值最大,最后执行
public class TransactionAspect {
@Around("@annotation(transactional)")
public Object manageTransaction(ProceedingJoinPoint joinPoint, Transactional transactional) throws Throwable {
System.out.println("【事务切面】开始执行 - Order 3");
System.out.println("开始事务");
try {
Object result = joinPoint.proceed();
System.out.println("提交事务");
return result;
} catch (Exception e) {
System.out.println("回滚事务");
throw e;
}
}
}
// 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface PermissionCheck {
String value();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface LogRecord {
String value();
}
执行顺序说明
// 业务方法
@Service
public class UserService {
@PermissionCheck("admin")
@LogRecord("查询用户信息")
@Transactional
public User getUserById(Long id) {
System.out.println("【业务方法】执行查询");
return new User(id, "测试用户");
}
}
执行顺序:
- 权限切面(@Order(1))先执行
- 日志切面(@Order(2))后执行
- 事务切面(@Order(3))最后执行
实现 Ordered 接口
@Aspect
@Component
public class FirstAspect implements Ordered {
@Override
public int getOrder() {
return 1; // 优先级最高
}
@Around("execution(* com.example.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("第一个切面执行");
return joinPoint.proceed();
}
}
@Aspect
@Component
public class SecondAspect implements Ordered {
@Override
public int getOrder() {
return 2;
}
@Around("execution(* com.example.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("第二个切面执行");
return joinPoint.proceed();
}
}
在配置类中统一管理顺序
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
@Bean
@Order(1)
public PermissionAspect permissionAspect() {
return new PermissionAspect();
}
@Bean
@Order(2)
public LogAspect logAspect() {
return new LogAspect();
}
}
复杂场景:同一连接点多个切面
// 更详细的示例,展示 Around 通知的执行流程
@Aspect
@Component
@Order(1)
public class FirstAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object firstAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("【第一切面】前置逻辑 - 开始执行");
System.out.println("【第一切面】当前时间: " + System.currentTimeMillis());
try {
Object result = joinPoint.proceed();
System.out.println("【第一切面】后置逻辑 - 执行成功");
return result;
} catch (Exception e) {
System.out.println("【第一切面】异常处理 - 捕捉异常");
throw e;
} finally {
System.out.println("【第一切面】最终处理 - 清理资源");
}
}
}
@Aspect
@Component
@Order(2)
public class SecondAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object secondAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("【第二切面】前置逻辑 - 开始执行");
System.out.println("【第二切面】方法参数: " + Arrays.toString(joinPoint.getArgs()));
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("【第二切面】后置逻辑 - 方法执行耗时: " + (endTime - startTime) + "ms");
return result;
}
}
注意点与最佳实践
执行顺序规则
// 对于 Around 通知,执行顺序如下: // @Order(1) 的前置逻辑 // @Order(2) 的前置逻辑 // 实际方法调用 // @Order(2) 的后置逻辑 // @Order(1) 的后置逻辑 // 形象比喻:就像层层包装 // 最外层包装(Order最小)先开始,最后结束 // 最内层包装(Order最大)后开始,先结束
最佳实践建议
@Component
@Order(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
public class PerformanceMonitorAspect {
// 性能监控应该在最外层
}
@Component
@Order(Ordered.LOWEST_PRECEDENCE) // 最低优先级
public class SecurityCheckAspect {
// 安全检查应该在最后执行
}
常见的切面顺序建议
- 缓存切面 - 最外层(@Order(1))
- 日志切面 - 第二层(@Order(2))
- 事务切面 - 第三层(@Order(3))
- 校验切面 - 最内层(@Order(4))
通过合理控制切面顺序,可以更好地组织和管理横切关注点,确保系统行为符合预期。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播