关于filter/springinterceptor/aop的拦截顺序

有目标就不怕路远。年轻人.无论你现在身在何方.重要的是你将要向何处去。只有明确的目标才能助你成功。没有目标的航船.任何方向的风对他来说都是逆风。因此,再遥远的旅程,只要有目标.就不怕路远。没有目标,哪来的劲头?一车尔尼雷夫斯基

导读:本篇文章讲解 关于filter/springinterceptor/aop的拦截顺序,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

背景

关于filter/springinterceptor/aop的加载顺序。filter指继承javax.servlet.Filter的;springinterceptor是spring里的拦截器,实现HandlerInterceptor的;aop是指@Aspect注解的类

这三种都可以拦截对controller方法进行拦截。那拦截顺序是怎么样的?

结论

顺序是分级的,filter/springinterceptor/aop三级。只要是filter就比springinterceptor先,只要是springinterceptor就比aop先。

  • filter和aop的内部顺序规则是一致的
  1. 如果不用@Order注解,相当于用 @Order(Integer.MAX_VALUE)
  2. 顺序按照@Order的值从小到大,如果值相同,就按照 “在项目中的先后顺序规则”
在项目中的先后顺序规则:
即出现在本项目中的位置,例如在IDEA中处于上面的就比下面的优先。例如filter/aop包名靠前,按包名顺序,假如同包名则按照文件名的顺序(不是按bean名字的顺序)。外部JAR包排在本项目之后,所以如果JAR包中存在@Order与本项目的@Order相同的时候,本项目排在上面会比较优先。

此规则的例子看附录
  • springinterceptor的顺序
    这个顺序比较特别,它不是通过@Order来决定的,它要有个配置类,配置类里的注册顺序就是顺序
@Configuration
public class SpringInterceptorConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SpringInterceptor3()).addPathPatterns("/**");
        registry.addInterceptor(new SpringInterceptor2()).addPathPatterns("/**");
        registry.addInterceptor(new SpringInterceptor()).addPathPatterns("/**");
    }

}

如果JAR包中的springinterceptor和本项目的springinterceptor也一起被扫描,这个顺序比较复杂。可以看实际的附录中的例子。
在这里插入图片描述

最佳实践

通常filter/springinterceptor/aop的执行顺序,不会引起大问题,但如果是顺序敏感,就必须确保它在最前面
(比如有个filter需要设置请求ID到ThreadLocal(MDC)中,如果它不是最前,其他filter若打印日志就不能从中获取到这个变量)

  • 对顺序敏感需要排在最前的,要设置 @Order(Integer.MIN_VALUE)
  • 保证一个项目只有一个 @Order(Integer.MIN_VALUE)
  • 保证@Order的值不一样,比如值都按照 @Order(Integer.MIN_VALUE)、0、10、20、30…这样子设置

补充问题

1、怎么证明如果不用@Order注解,相当于用 @Order(Integer.MAX_VALUE)

结论是实际测试出来的,同学们更应该去查源码,这里为了图省事直接做实验观察

可以这么证明弄两个filter(A和B),一个用@Order(Integer.MAX_VALUE)另一个不写。

  1. 看顺序,再反过来,看到结果是一样的,说明两者是相同的,但需要进一步
  2. 假如顺序是AB,且B上的注解是@Order(Integer.MAX_VALUE),A上无注解,此时顺序是AB,那我把B上的改成@Order(Integer.MAX_VALUE-1),则打印出BA
    经过这两个步骤,证明,不写注解那就是@Order(Integer.MAX_VALUE)

附录

  1. 以下是JAR包中的filter/springinterceptor/aop也被扫描,和本项目中的一起排顺序。最终打印出拦截的结果是

备注:打印出host的是宿主项目,打印出SUB的是被引入的JAR包,其中本项目和JAR包的filter3/2/1以及AOP aspect3/2/1,都配成@Order(0)/10/20,

host Filter3 begin
SUB Filter3 begin
host Filter2 begin
SUB Filter2 begin
host Filter begin
SUB Filter begin
host springinterceptor3: preHandle
host springinterceptor2: preHandle
host springinterceptor: preHandle
SUB springinterceptor3: preHandle
SUB springinterceptor2: preHandle
SUB springinterceptor: preHandle
----- host AOP aspect3 ---- begin
----- SUB AOP aspect3 ---- begin
----- host AOP aspect2 ---- begin
----- SUB AOP aspect2 ---- begin
----- host AOP aspect ---- begin
----- SUB AOP aspect ---- begin
----- SUB AOP aspect ---- end
----- host AOP aspect ---- end
----- SUB AOP aspect2 ---- end
----- host AOP aspect2 ---- end
----- SUB AOP aspect3 ---- end
----- host AOP aspect3 ---- end
SUB springinterceptor: postHandle
SUB springinterceptor2: postHandle
SUB springinterceptor3: postHandle
host springinterceptor: postHandle
host springinterceptor2: postHandle
host springinterceptor3: postHandle
SUB springinterceptor: afterCompletion
SUB springinterceptor2: afterCompletion
SUB springinterceptor3: afterCompletion
host springinterceptor: afterCompletion
host springinterceptor2: afterCompletion
host springinterceptor3: afterCompletion
SUB Filter end
host Filter end
SUB Filter2 end
host Filter2 end
SUB Filter3 end
host Filter3 end

可以看到结论是:filter第一级最优先,springinterceptor第二级,aop第三极。在filter内部,并非本项目的filter就比JAR包中的优先,是平等地要看@Order的值,值相同的再看 “在项目中的先后顺序规则”;

springinterceptor的内部规则比较复杂,由于有两个配置类将对应的拦截器注册,所以顺序是等host的全部完毕再打印JAR包里的springinterceptor。

aop的内部规则和filter完全一样。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135273.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!