@RefreshScope和过滤器Filter不要这样用

简介: 在注册自定义的OncePerRequestFilter所在的类上加了@RefreshScope导致自定义的OncePerRequestFilter不会被注册到上下文。

1、问题

最近在一个Spring应用中碰到这样的问题:Spring过滤器OncePerRequestFilterdoFilterInternal方法一直不被执行。最终发现是因为:在注册自定义的OncePerRequestFilter所在的类上加了@RefreshScope导致自定义的OncePerRequestFilter不会被注册到上下文。

模拟的代码如下:

自定义的Filter:

@Slf4j
public class CustomFilter extends OncePerRequestFilter {
    public CustomFilter() {
        log.warn("=================init CustomFilter====================");
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setStatus(200);
        response.setHeader("Content-Type", "application/json");
        response.getWriter().write("{\"age\":12}");
        response.getWriter().flush();
        response.flushBuffer();
//        filterChain.doFilter(request, response);
    }
}

使用@RefreshScope注解的类

@Configuration
@Slf4j
@RefreshScope
public class WebConfiguration implements WebMvcConfigurer {
    @Bean
    public CustomFilter customFilter() {
        return new CustomFilter();
    }
}

2、寻找原因

对于这个问题,在Google上也没搜索到合适的解答,自己在源码里打了断点,发现这个CustomFilter没有被执行init方法,所以最终也不会打印Filter xxx configured for use的日志,也就是说不会被注册进上下文。

我们知道filter过滤器是用于过滤请求的URL,遵循Servlet规范的,需要实现javax.servlet.Filter接口,依赖于Tomcat等容器。

Filter有3个的生命周期:服务启动时-init(FilterConfig arg0)、服务停止时-destroy()、拦截请求时-doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain)

只有过滤器执行了init方法,才能被注册进上下文。那上面自定义的过滤器CustomFilter为什么没有被执行init方法呢。

继续查阅了@ScopeRefesh相关原理,我们知道RefreshScope之所有能做热加载,主要做了以下动作:

  1. 单独管理Bean生命周期
    创建Bean的时候如果是RefreshScope就缓存在一个专门管理的ScopeMap中,这样就可以管理Scope是Refresh的Bean的生命周期了。
  2. 重新创建Bean
    外部化配置刷新之后,会触发一个动作,这个动作将上面的ScopeMap中的Bean清空,这样,这些Bean就会重新被IOC容器创建一次,使用最新的外部化配置的值注入类中,达到热加载新值的效果。

@ScopeRefesh也有失效的场景,RefreshBean被正确加载为CGLib动态代理对象就能正常动态刷新,有些不正常加载的场景,则会失效。比如组装加载WebFilter的时候会有两个重复Filter,一个是变化的,一个是不变化的。在Web应用里实际取到的是不变化的,所以修改配置会失效。

3、未果,惨淡收场

结合现状和原理来看,我还是未能破解这个谜题。上文中的问题是加载出了2个Filter,导致失效,而我这里出现的问题是自定义的Filter没有被加载。

我的猜测是,这个自定义Filter可能也是被创建了2个Bean,Bean-A是走了init方法,但实际应用中取到的Bean-B,由于某些原因,Bean-B再次创建的时候,没有走init方法,所以导致没有被注册到上下文。

或者是只创建一个Bean,但是由于使用@RefreshScope创建的Filter Bean缺少什么机制,导致没有被当作一种Filter去执行初始化。

折腾了几个小时,最终也没分析出个原因。这里只能给朋友们提个醒,@RefreshScope和过滤器Filter不要这样一起使用,否则会导致OncePerRequestFilterdoFilterInternal方法一直不被执行。

如果有知道谜底的朋友也请帮我解答下,谢谢!!!

文中查阅的RefreshScope的原理,参考了这篇CSDN博主Static_lin的文章《从RefreshScope实现原理看刷新配置失效问题》,文章用源码将原理分析的比较透彻。

总结:本文简单分析@RefreshScope和过滤器Filter一起使用出现的问题,最终谜底仍未解开,只能给朋友们提个醒了。

本篇完结!感谢你的阅读,欢迎点赞 关注 收藏 私信!!!

原文链接:http://www.mangod.top/articles/2023/09/02/1693623653306.htmlhttps://mp.weixin.qq.com/s/vZCjamIzDGgRef_m1YbXHA

相关文章
|
3月前
|
Java 测试技术 API
Java Stream API:被低估的性能陷阱与优化技巧
Java Stream API:被低估的性能陷阱与优化技巧
388 114
|
存储 JSON SpringCloudAlibaba
Sentinel使用及规则配置
Sentinel使用及规则配置
2505 0
Sentinel使用及规则配置
|
3月前
|
存储 安全 Java
《数据之美》:Java集合框架全景解析
Java集合框架是数据管理的核心工具,涵盖List、Set、Map等体系,提供丰富接口与实现类,支持高效的数据操作与算法处理。
|
3月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
174 8
|
机器学习/深度学习 人工智能 分布式计算
蚁群、蜂群的智慧,大模型也可以有,谷歌等机构群体智能研究亮相
蚁群和蜂群以其独特的群体智能行为著称,如分布式决策、自组织性和鲁棒性。这些特性启发了科学家将群体智能原理应用于大模型的构建,以实现更高效、更智能的系统。谷歌等机构已通过模拟这些行为,开发出如“蚁群优化”算法等成果,显著提高了计算效率和系统的鲁棒性。然而,群体智能的应用仍面临通信协调、个体差异性和可解释性等挑战。
488 3
|
测试技术 开发者
单元测试问题之在Mockito中静态方法的调用,如何模拟
单元测试问题之在Mockito中静态方法的调用,如何模拟
|
人工智能 算法 PyTorch
【人工智能】Transformers之Pipeline(四):零样本音频分类(zero-shot-audio-classification)
【人工智能】Transformers之Pipeline(四):零样本音频分类(zero-shot-audio-classification)
314 0
|
Java
Java动态获取某个接口下所有的实现类对象集合
Java动态获取某个接口下所有的实现类对象集合
683 1
|
存储 安全 Java
提升编程效率的利器: 解析Google Guava库之集合篇Multimap(二)
提升编程效率的利器: 解析Google Guava库之集合篇Multimap(二)
|
XML 设计模式 JavaScript
JVM第三讲:JVM 基础-字节码的增强技术详解
JVM第三讲:JVM 基础-字节码的增强技术详解
555 0
JVM第三讲:JVM 基础-字节码的增强技术详解

热门文章

最新文章