前言
在
SpringBoot
系列文章的《第七章:过滤器、监听器、拦截器》中,小技巧中指出,可使用@Order
设置过滤器的执行顺序。由于没有自己求证过,看了相关材料后,想当然的写进了文章中,这个进行更正下。
通过过滤器名称
和设置@Order
的方法都是不行的。抱歉了,各位。之后在编写文章时,会本着负责且持着大胆猜测小心求证的态度,会对相关事项进行核对的!再次,抱歉,误导了大家
这里要感谢简书网友:形而上学本尊,指出此错误!再次感谢!
正确设置排序方式
《第七章:过滤器、监听器、拦截器》也有指出,利用
FilterRegistrationBean
可以设置排序顺序。那是否还有其他方式呢。有的,只是这种方案不是很优雅。这里简单说明下。
先说结论:可以通过过滤器
的类名进行约定排序。
浅谈ServletComponentScan注解的启动方式
既然遇到了,那就简单分析下使用
@WebFilter
和@ServletComponentScan
的启动方式吧。
首先我们来看下,注解@ServletComponentScan
(删除了相关注解):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 (ElementType.TYPE)
(RetentionPolicy.RUNTIME)
(ServletComponentScanRegistrar.class)
public ServletComponentScan {
"basePackages") (
String[] value() default {};
"value") (
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
简单来说,此注解就是指定扫描路径的,通过value
、basePackages
或者basePackageClasses
。主要还是看下ServletComponentScanRegistrar
类,这才是关键。
1 | class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar { |
可以看见,它是一个ImportBeanDefinitionRegistrar
的实现类,ImportBeanDefinitionRegistrar
可以动态地装载Bean
。再来看看ServletComponentRegisteringPostProcessor
类,此类是个BeanFactoryPostProcessor
,BeanFactory的后置处理器,简单理解就是扩展点吧。启动的时候会调用postProcessBeanFactory
方法。ServletComponentRegisteringPostProcessor
源码就不贴了,简单来说,它的作用就是:扫描被@WebServlet
、@WebFilter
及@WebListener
的类,最后通过对应的ServletRegistrationBean
、FilterRegistrationBean
及ServletListenerRegistrationBean
进行注册。看见这些是不是很熟悉了。1
2
3
4
5
6
7
8//部分代码
static {
List<ServletComponentHandler> servletComponentHandlers = new ArrayList<ServletComponentHandler>();
servletComponentHandlers.add(new WebServletHandler());
servletComponentHandlers.add(new WebFilterHandler());
servletComponentHandlers.add(new WebListenerHandler());
HANDLERS = Collections.unmodifiableList(servletComponentHandlers);
}
关键看这个方法scanPackage
:1
2
3
4
5
6
7
8
9
10
11
12
13private void scanPackage(
ClassPathScanningCandidateComponentProvider componentProvider,
String packageToScan) {
for (BeanDefinition candidate : componentProvider
.findCandidateComponents(packageToScan)) {
if (candidate instanceof ScannedGenericBeanDefinition) {
for (ServletComponentHandler handler : HANDLERS) {
handler.handle(((ScannedGenericBeanDefinition) candidate),
(BeanDefinitionRegistry) this.applicationContext);
}
}
}
}
可以看见,通过componentProvider.findCandidateComponents(packageToScan)
方法获取到对应的注解类,同时判断是否为以上说的三种,最后调用其doHandle
方法完成注册功能。以下是WebFilterHandler
的doHandler
方法。
现在,我们看看findCandidateComponents
方法怎么获取对应注解类的。
断点之后,可以看见是AnnotationConfigEmbeddedWebApplicationContext
类,
继续断点进去,最后是使用PathMatchingResourcePatternResolver
类进行资源获取的。
通过递归的方式,获取所有的类:
最后关键就是这个Arrays.sort(dirContents)
了。所以简单来说,可以通过class类名来达到排序效果。但这种方案要限制类名,还是使用FilterRegistrationBean
之类的来设置吧。
总结
写的可能有点乱也有点水,⊙﹏⊙‖∣。主要还是想纠正下原先的错误,O__O…。知其然知其所以然,还有很长的路要走。没有写里面的细节,只是大致讲解了下。有兴趣的可以自行跟踪看看。
最后
目前互联网上很多大佬都有
SpringBoot
系列教程,如有雷同,请多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有所错误之处,还望提出,谢谢。
老生常谈
- 个人QQ:
499452441
- 微信公众号:
lqdevOps
个人博客:http://blog.lqdev.cn