混合切面类型 (Mixing Aspect Types)
在同一个配置中,完全可以混合使用通过自动代理支持实现的 @AspectJ 风格切面、基于 Schema 定义的 <aop:aspect> 切面、<aop:advisor> 声明的 Advisor,甚至还包括其他风格的代理和拦截器。所有这些都是基于相同的基础支撑机制实现的,可以毫无困难地共存。
补充教学
1. 为什么可以混合使用?
虽然 AOP 的声明方式(注解、XML、API)各不相同,但 Spring AOP 在底层实现上是高度统一的:
- 统一的拦截器链:无论你用哪种方式定义的通知,Spring 最终都会将它们转化为统一的 Advisor 对象(包含一个 Pointcut 和一个 Advice)。
- 责任链模式:最终执行时,所有匹配的通知都会被放入一个“拦截器链”中,按顺序依次执行。
2. 混合使用的典型场景
在现实的企业级项目中,混合使用非常常见:
- 声明式事务:通常通过 XML 的
<tx:advice>或注解的@Transactional(本质是基础级 Advisor)来处理。 - 业务监控:使用
@AspectJ注解编写自定义切面,方便快捷。 - 老代码集成:在一个已经存在大量 XML 配置的老项目中,新功能采用
@AspectJ注解开发,两者可以完美融合。
3. 如何确保顺序?
当你混合使用不同的 AOP 风格时,排序(Ordering) 变得尤为重要:
- 实现
Ordered接口:这是最通用的方式。无论是 XML 定义的 Bean 还是标注了@Aspect的类,都可以实现此接口。 - 使用
@Order注解:适用于标注了@Aspect的类。 - XML 属性:在
<aop:aspect>或<aop:advisor>标签上直接设置order属性。
4. 配置建议
为了让各种风格协调工作,请注意以下几点:
- 启用自动代理:确保你的配置中包含了
@EnableAspectJAutoProxy(Java) 或<aop:aspectj-autoproxy />(XML),这是让@AspectJ切面生效的前提。 - 避免重复通知:如果一个切点同时被 XML 方案和 @AspectJ 方案匹配,该方法会被拦截两次。务必检查切入点表达式(Pointcut Expression),防止逻辑重叠。
- 统一风格:虽然支持混合,但从可维护性角度考虑,建议团队对自定义业务切面规定一种统一的风格(通常首选 @AspectJ),仅在集成框架功能(如事务、缓存)时使用专用的配置风格。