【问题标题】:Spring - Unable to instantiate a component object in request scopeSpring - 无法在请求范围内实例化组件对象
【发布时间】:2015-05-27 15:17:42
【问题描述】:

我正在尝试实例化一个组件对象,我在 applicationContext.xml 中为其声明了 <bean> 条目。实例化我的目标组件类的流程如下

CalculateController -> CalculateService -> CalculateComponent

在哪里

CalculatorController - 范围 = 请求,使用 @Controller 注释并包含在 webapplicationContext.xml 中的组件扫描中

CalculatorService - Scope = 单例,使用@service 注释并包含在 applicationContext.xml 中的组件扫描中

CalculateComponent - 范围 = 请求,无注释,从 webapplicationConext.xml 和 applicationContext.xml 中的组件扫描中排除。在 webApplicationContext.xml 中定义了 bean 条目,范围 = request。还包括 <aop:scoped-proxy/><bean> 定义中。

我在 web.xml 中包含了以下条目

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
            classpath:spring/applicationContext.xml
            /WEB-INF/mvc-dispatcher-servlet.xml
            ....Other resource xmls
    </param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- To retrieve session related information -->
<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

<listener>
    <listener-class>
            org.springframework.web.context.request.RequestContextListener 
    </listener-class>
</listener> 


<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

请注意,CalculateComponent 有一个 3 参数 ref 对象构造函数,并且它们三个在 webApplicationContext.xml 中都有 &lt;bean&gt; 条目,具有单例范围并且它们没有注释。

当请求发送创建CalculateComponent对象时,spring容器抛出如下错误。

"No thread-bound request found: 你指的是request 实际 Web 请求之外的属性,或处理请求 在最初接收线程之外?如果你真的 在 Web 请求中运行并仍收到此消息,您的 代码可能在外部运行 DispatcherServlet/DispatcherPortlet:在这种情况下,使用 RequestContextListener 或 RequestContextFilter 暴露当前 请求。”

请指教。

更新:

当我从 contextConfigLocation 中删除 /WEB-INF/mvc-dispatcher-servlet.xml 并启动服务器时,我得到了 Autowired failed 错误 - “No qualifying bean of type CalculateComponent found for dependency:”,即使在我更改了范围从请求到单例。

然后我在CalculateService 中注释掉了CalculateComponent 的自动装配,现在我可以看到CalculateComponent 启动了两次(正如我的@Serge Ballesta 所提到的)。所以我得出结论,CalculateService 是通过 ContextLoaderListener(applicationContext.xml 中的 bean 条目)在加载 DispatcherServlet 之前启动的(即没有加载 mvc-dispatcher-servlet 中提到的 bean)。

我在 contextConfigLocation 中再次添加了 /WEB-INF/mvc-dispatcher-servlet.xml,但这次是作为第一个条目(即在 applicationContext.xml 之上)。现在,CalculateComponent 再次加载了两次,并且自动装配是在单例范围内完成的。通过此设置,我将 CalculateComponent 范围更改回 request,但再次出现“我得到 No thread-bound request found”错误。

所以问题是,

ContextLoaderListener 试图在 DispatcherServlet(CalculateComponent) 加载/可用之前对其资源进行初始化。

【问题讨论】:

    标签: spring spring-ioc


    【解决方案1】:

    有一个请求范围的控制器很奇怪...... AFAIK,框架希望它是一个单例。尝试将其放在单例范围内。

    而且我认为你已经将来自/WEB-INF/mvc-dispatcher-servlet.xml 的所有 bean 实例化了两次:

    • 首先在全局 contextConfigLocation 中声明的根应用程序上下文中
    • 在名为 mvc-dispatcher 的 servlet 的 servlet 应用程序上下文中的下一个

    您应该重命名文件,使其不是作为 servlet 应用程序上下文的加载程序,或者将其从根上下文中删除

    【讨论】:

    • 我从所有控制器中删除了@scope 值,并从 context-param 中删除了条目 /WEB-INF/mvc-dispatcher-servlet.xml。现在,当我启动服务器时,我收到错误“没有为依赖项找到CalculateComponent 类型的合格bean:预计至少有1 个bean 有资格作为此依赖项的自动装配候选者。依赖项注释:{@org.springframework.beans.factory .annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value="BeanDefNameForCalcualteComponenet"
    • @Gopal : 现在是一个更标准的错误...当您使用代理在单例中连接请求范围的 bean 时,必须连接 CalculateComponent作为接口,因为默认情况下 Spring 使用 JDK 代理。您可以强制使用 javassist 类代理 (proxy_target_class = true),但不要同时使用两者。
    • 感谢您的回复。将 添加到请求范围 bean 不足以代理类。我还在 pom.xml 中添加了 cglib。
    • @Gopal:是的,它实际上是 cglib,您正确地修复了我的评论 :-)
    • 如果您可以从我的问题中看到,我正在为请求范围的 bean 使用 aop 范围代理,但我仍然收到错误消息。请指教。
    【解决方案2】:

    回答我自己的问题。正如我在问题中提到的,这是我获取请求范围组件 bean 的流程。

    CalculateController -> CalculateService -> CalculateComponent。

    但CalculateController 是通过异步请求调用的。 我们无法从异步请求线程访问网络范围的 bean。

    参考:How to enable request scope in async task executor

    【讨论】:

      猜你喜欢
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多