以下是Spring Boot中对同一接口定义多个切面的示例,分别通过接口方式和注解方式实现切面排序,并对比差异:
一、接口方式实现切面排序
1. 定义接口
// 服务接口
public interface MyService {void methodA();void methodB();
}// 接口实现类
@Service
class MyServiceImpl implements MyService {@Overridepublic void methodA() {System.out.println("Executing methodA");}@Overridepublic void methodB() {System.out.println("Executing methodB");}
}
2. 定义切面(实现 Ordered
接口)
// 切面A:优先级高(Order=1)
@Component
@Aspect
public class AspectA implements Ordered {@Overridepublic int getOrder() {return 1; // 数值越小,优先级越高}@Before("execution(* com.example..MyService.*(..))")public void beforeA() {System.out.println("AspectA before advice");}
}// 切面B:优先级低(Order=2)
@Component
@Aspect
public class AspectB implements Ordered {@Overridepublic int getOrder() {return 2;}@Before("execution(* com.example..MyService.*(..))")public void beforeB() {System.out.println("AspectB before advice");}
}
3. 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAspect {@Autowiredprivate MyService myService;@Testpublic void testOrder() {myService.methodA();// 输出顺序:AspectA before -> AspectB before -> methodA}
}
二、注解方式实现切面排序
1. 定义切面(使用 @Order
注解)
// 切面C:优先级高(Order=1)
@Component
@Aspect
@Order(1)
public class AspectC {@Before("execution(* com.example..MyService.*(..))")public void beforeC() {System.out.println("AspectC before advice");}
}// 切面D:优先级低(Order=2)
@Component
@Aspect
@Order(2)
public class AspectD {@Before("execution(* com.example..MyService.*(..))")public void beforeD() {System.out.println("AspectD before advice");}
}
2. 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAspect {@Autowiredprivate MyService myService;@Testpublic void testAnnotationOrder() {myService.methodB();// 输出顺序:AspectC before -> AspectD before -> methodB}
}
三、两种方式的对比表格
特性 | 接口方式(Ordered ) | 注解方式(@Order ) |
---|---|---|
实现方式 | 实现 Ordered 接口,重写 getOrder() 方法 | 在切面类上添加 @Order(int value) 注解 |
优先级规则 | 数值越小,优先级越高 | 数值越小,优先级越高 |
适用场景 | 传统方式,需继承接口 | 推荐方式,更简洁 |
局限性 | 需要额外实现接口 | 无额外继承要求 |
Spring 内部处理 | 通过 OrderComparator 比较 | 直接解析 @Order 注解 |
四、关键点总结
-
切面执行顺序:
- 两者均通过数值控制优先级,
Order=1
的切面比Order=2
的切面先执行。 - 若未指定顺序,Spring 默认按声明顺序加载,但结果不可靠,建议显式设置。
- 两者均通过数值控制优先级,
-
推荐实践:
- 优先使用注解方式(
@Order
),代码更简洁且符合 Spring 的注解驱动风格。 - 若需复用排序逻辑,可结合
Ordered
接口实现通用排序策略。
- 优先使用注解方式(