【问题标题】:Request scope being initialised multiple times请求范围被多次初始化
【发布时间】:2015-05-18 10:50:47
【问题描述】:

我正在构建一个 Spring Boot Web 应用程序,并且我有一个请求范围的 bean。

我正在使用 Spring Security,并且需要访问过滤器链中的请求范围 bean(DispatcherServlet 之前),所以我注册了 RequestContextListener 以使其可用 - 一切正常:我可以自动装配将作用域 bean 请求到我的过滤器链中并可以使用它。但是,似乎请求范围的 bean 在 Spring 安全过滤器链之后被重新初始化。

以下日志:

May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] Checking match of request : '/app/test'; against '/logout'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 5 of 12 in additional filter chain; firing Filter: 'SystemSecurityFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] Checking match of request : '/app/test'; against '/________site-memory-status'
May 18 06:19:40 DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] Checking match of request : '/app/test'; against '/________site-monitor'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 6 of 12 in additional filter chain; firing Filter: 'RequestScopeFilter'
May 18 06:19:40 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] Creating instance of bean 'scopedTarget.requestScopedBean'
May 18 06:19:40 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] Returning cached instance of singleton bean 'application'
May 18 06:19:40 INFO  [com.test.app] Creating RequestScopedBean.
May 18 06:19:40 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] Finished creating instance of bean 'scopedTarget.requestScopedBean'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy] Delegating to org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
May 18 06:19:40 DEBUG [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /app/test; Attributes: [permitAll]
May 18 06:19:40 DEBUG [org.springframework.security.access.vote.AffirmativeBased] Voter: org.springframework.security.web.access.expression.WebExpressionVoter, returned: 1
May 18 06:19:40 DEBUG [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] Authorization successful
May 18 06:19:40 DEBUG [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] RunAsManager did not change Authentication object
May 18 06:19:40 DEBUG [org.springframework.security.web.FilterChainProxy] /app/test reached end of additional filter chain; proceeding with original chain
May 18 06:19:40 INFO  [com.test.app] Creating RequestScopedBean.
May 18 06:19:40 DEBUG [org.springframework.web.servlet.DispatcherServlet] DispatcherServlet with name 'dispatcherServlet' processing GET request for [/app/test]
May 18 06:19:40 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] Returning cached instance of singleton bean 'AppController'

您将看到“Creating RequestScopedBean”这一行——它记录在我的请求范围 bean 的构造函数中,并被调用两次——一次是在我的自定义过滤器被调用时 (RequestScopeFilter),然后在将过滤器链移交给DispatchServlet。这是预期的行为吗?它更早可用似乎很奇怪,但仍然在DispatcherServlet 重新初始化 - 假设它只是可配置的,但在 RequestContextListener 上看不到任何选项。我想也许我应该换成RequestContextFilter 并使用setThreadContextInheritable 方法来看看是否能达到我想要的效果,但找不到任何关于何时使用另一种方法的明确建议。


更新

好的,这是我一周内第二次在 SO 上成为白痴 - 实际上 Spring 并没有两次初始化 bean,而是我的过滤器被执行了两次,并且我对请求范围 bean 所做的更改正在记录相同的消息。

下一个问题是为什么过滤器会执行两次?我唯一的猜测是因为我已将过滤器注册为 Spring @Bean 并将其显式添加到我的 Spring 过滤器链中。我应该更改为实现OncePerRequestFilter,还是有其他配置可以阻止它作为我的 Spring Security 过滤器链的一部分执行?

【问题讨论】:

  • 奇怪的是,第一行调用了一个 bean 创建(在 Creating instanceFinished Creating instance 之间),而另一行则没有.但在不知道什么是 RequestScopeFilter 或 RequestScopedBean 的情况下,我不能说更多。
  • 谢谢@SergeBallesta - 我已经更新了问题,主要是我的错误,但现在导致了另一个问题..
  • 如果您将其添加为@Bean,spring boot 将检测到它并将其注册为常规过滤器,现在如果您还将其添加到 spring 安全链中,它将执行两次。最简单的方法是删除@Bean 注释。
  • 我需要在我的请求范围 bean 中自动装配到过滤器,如果过滤器没有注册为 bean,这将不起作用。我已更改为扩展 OncePerRequestFilter 并且似乎已修复它。

标签: java spring spring-mvc spring-boot


【解决方案1】:

问题是由于我在过滤器中显式初始化了请求范围的 bean(我在 bean 中设置了一些特定于请求的状态)并且愚蠢地记录了相同的消息。

根本原因是我的过滤器被执行了两次,一次是作为 Spring Security 链的一部分,然后又是由 Spring,因为我还将过滤器注册为 Spring bean,因此也自动添加为普通过滤器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 2015-08-14
    • 2014-06-21
    • 2013-06-16
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    相关资源
    最近更新 更多