0

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

计算控制器 -> 计算服务 -> 计算组件

在哪里

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 对象构造函数,它们三个都<bean>在 webApplicationContext.xml 中具有单例范围的条目,并且它们没有注释。

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

“未找到线程绑定请求:您是指实际 Web 请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上是在 Web 请求中操作并且仍然收到此消息,那么您的代码是可能在 DispatcherServlet/DispatcherPortlet 之外运行:在这种情况下,使用 RequestContextListener 或 RequestContextFilter 来公开当前请求。”

请指教。

更新:

当我从 contextConfigLocation 中删除 /WEB-INF/mvc-dispatcher-servlet.xml 并启动服务器时,我得到了 Autowired failed 错误 - “No qualifying bean of type of 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) 加载/可用之前对其资源进行初始化。

4

2 回答 2

0

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

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

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

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

于 2015-05-28T14:29:27.780 回答
0

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

计算控制器 -> 计算服务 -> 计算组件。

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

参考:如何在异步任务执行器中启用请求范围

于 2015-06-01T20:43:47.490 回答