@Order属性与通知执行先后顺序

本文解决MyBatis配置多数据源时的数据源切换失败问题。通过调整自定义切面与Spring事务切面的执行顺序,确保正确切换数据源。详细介绍了使用AOP配置的不同切面及order属性的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

申明:本文转载至https://www.cnblogs.com/zjrodger/p/5633922.html,如有侵权,请及时告知,本人将立即删除。

【障碍再现】

    MyBatis配置多数据源时,数据源切换失败。

【原因分析】
    自定义切面和Spring自带事务切面“即<aop:advisor>”执行的先后顺序导致数据源不能切换成功。

【解决方案】

1、配置代码

1 <aop:config>                    
2     <!-- 1、Spring框架自身提供的切面 -->
3     <aop:advisor advice-ref="userTxAdvice" pointcut="execution(public * com.zjrodger.*.service..*.*(..))" order="2"/>                                
4     <!-- 2、用户自定义的切面,根据切入点,动态切换数据源。 -->        
5     <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor" order="1">                                        
6         <aop:before method="setdataSourceBakDb"  pointcut="execution(* com.zjrodger.bakdata.service..*.*(..))"/>                        
7         <aop:before method="setdataSourceHuihangDb"  pointcut="execution(* com.zjrodger.datatobank.service..*.*(..))"/>    
8     </aop:aspect>        
9 </aop:config>

2、说明

    在AOP中,当执行同一个切入点时,不同切面的执行先后顺序是由“每个切面的order属性”而定的,order越小,则该该切面中的通知越先被执行。
上述<aop:config>元素中,引用了两个切面类:“userTxAdvice类”和“dataSourceAspect类”,其中<aop:advisor>是Spring框架自定义的切面标签。
根据两个切面类order属性的定义,当程序执行时并且触发切入点后(即调用
com.zjrodger.bakdata.service包及其子包下的方法),dataSourceAspect切面类中的setdatasourceBakDb()方通知法首先执行,之后才会执行userTxAdvice事务类中的相关通知方法。

【拓展】
若不想设置Order属性,如何能决定不同切面类中通知执行的先后顺序?
答:可以调整,在不定义Order属性的前提下,可以通过切面类的定义顺序来决定通知执行的先后顺序。
    但需要特别注意的是,若<aop:config>元素中同时存在“<aop:advisor>”元素和“<aop:aspect>元素”(“<aop:pointcut>元素” 可有可无),则它们元素必须按照< aop:pointcut >,<aop:advisor>和<aop:aspect>此顺序来定义
    正因为“<aop:advisor>”元素和“<aop:aspect>元素”定义顺序是不能调整的,从而导致在没有指定 “order属性”的前提下,“<aop:advisor>”元素对应切面类中通知的执行顺序优先于“<aop:aspect>元素” 对应切面类中通知的执行。
    此时,只能通过指定Order属性来调整这两个切面类中通知执行的先后顺序了。

【结论】
(1)在AOP中,当执行同一个切入点时,不同切面的执行先后顺序是由“每个切面的order属性”而定的,order越小,则该该切面中的通知越先被执行。

(2)不定义Order属性,通过切面类的定义顺序来决定通知执行的先后顺序
若不同切面类执行时,在没有定义“order属性”,而且切面类中触发增强通知的切入点都相同,则在切面类中的通知的执行顺序与该切面类在<aop:config>元素中“声明的顺序”相关,即先声明的切面类先执行,后声明的切面类后执行



<think>好的,用户的问题是关于Spring中@Order注解执行顺序无效的原因以及解决方案。我需要结合提供的引用资料和我的知识来回答这个问题。 首先,用户提到@Order注解无效,这可能Spring和Servlet容器之间的差异有关。根据引用[2],@WebFilter、@WebServlet等注解属于Servlet容器,而Spring容器不处理这些注解。所以如果用户是在Filter类上使用@Order,可能不起作用,因为Spring并不管理这些组件的顺序。 接下来,引用[3]提到ApplicationFilterFactory创建过滤器链,而过滤器的顺序由Servlet容器决定。这可能意味着即使Spring中使用了@Order,Servlet容器仍按自己的规则处理,比如按类名排序,导致顺序不符合预期。 解决方案方面,引用[2]指出需要在Spring配置类中显式配置Filter,例如使用FilterRegistrationBean。这样可以明确指定顺序,因为FilterRegistrationBean有setOrder方法。另外,需要确保不要使用@WebFilter注解,避免冲突。 还需要检查是否有多个FilterRegistrationBean配置,或者是否使用了错误的注解导致Spring无法识别顺序。可能用户混淆了Spring管理的Bean和Servlet容器管理的组件,导致@Order不生效。 总结起来,主要原因可能是过滤器由Servlet容器管理,而@Order属于Spring,两者不互通。解决方法是在Spring配置中注册Filter并设置顺序,避免使用Servlet注解。</think>### @Order 注解执行顺序无效的原因及解决方案 在 Spring 框架中,`@Order` 注解通常用于控制 Bean 的加载顺序或拦截器、AOP 切面执行顺序。但若其未按预期生效,可能以下原因相关: --- #### 1. **容器层级差异导致失效** - **原因**:`@Order` 注解在 Spring 容器中生效,但部分组件(如 `Filter`、`Servlet`)由 **Servlet 容器**(如 Tomcat)直接管理,而非 Spring 容器。例如,使用 `@WebFilter` 注解的过滤器会被 Servlet 容器初始化,此时 `@Order` 无法控制其执行顺序[^2]。 - **解决方案**: 显式通过 Spring 配置类注册过滤器,并手动指定顺序: ```java @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<MyFilter1> filter1() { FilterRegistrationBean<MyFilter1> registration = new FilterRegistrationBean<>(); registration.setFilter(new MyFilter1()); registration.addUrlPatterns("/*"); registration.setOrder(1); // 通过 setOrder() 指定顺序 return registration; } } ``` --- #### 2. **过滤器链构建机制问题** - **原因**:Servlet 容器(如 Tomcat)通过 `ApplicationFilterFactory` 构建过滤器链时,默认按类名或配置顺序加载过滤器,而非依赖 `@Order`[^3]。 - **解决方案**: 避免依赖 `@WebFilter` 注解的自动注册,改用 `FilterRegistrationBean` 手动注册所有过滤器,并明确设置顺序。 --- #### 3. **作用范围不匹配** - **原因**:`@Order` 注解对 **同一容器内的 Bean** 生效。若组件未由 Spring 管理(如未添加 `@Component` 注解),或属于不同容器(如父子容器),则顺序控制会失效。 - **解决方案**: 确保组件被 Spring 管理(如添加 `@Component` 或 `@Bean` 注解),并检查容器层级结构。 --- #### 4. **依赖冲突或重复配置** - **原因**:存在多个 `FilterRegistrationBean` 配置同一过滤器,或其他框架(如 Spring Security)的过滤器链冲突。 - **解决方案**: 检查所有过滤器配置,确保唯一性,并调整顺序避免覆盖。 --- ### 总结步骤 1. **确认组件是否由 Spring 管理**:使用 `@Component` 或 `@Bean` 注解。 2. **避免 Servlet 容器注解**:如 `@WebFilter`,改用 `FilterRegistrationBean` 注册过滤器。 3. **手动指定顺序**:通过 `setOrder()` 方法设置优先级。 4. **检查容器层级依赖冲突**:确保无重复配置或框架干扰。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值