gpt4 book ai didi

spring-mvc - Spring MVC : How to use a request-scoped bean inside a spawned thread?

转载 作者:行者123 更新时间:2023-12-02 22:44:39 28 4
gpt4 key购买 nike

在 Spring MVC 应用程序中,我有一个请求范围的 bean。我把这颗 bean 注入(inject)到某处。在那里,HTTP 请求服务线程可能会生成一个新线程。

但是每当我尝试从新生成的线程访问请求范围的 bean 时,我都会收到 org.springframework.beans.factory.BeanCreationException (请参阅下面的堆栈跟踪)。
从 HTTP 请求线程访问请求范围的 bean 工作正常。

如何使请求范围的 bean 可用于 HTTP 请求线程生成的线程?

<小时/>

简单设置

运行以下代码片段。然后启动服务器,例如http://example.com:8080 .
当访问http://example.com:8080/scopetestnormal时,每次向该地址发出请求时,counter 都会增加 1(通过记录器输出可注意到)。 :) super !

访问http://example.com:8080/scopetestthread时,每次向该地址发出请求时,都会引发上述异常。 :(。无论选择什么 ScopedProxyMode,基于 CGLIB 的都会发生这种情况基于 JDK 动态代理接口(interface)的请求范围 bean

配置文件

package com.example.config

@Configuration
@ComponentScan(basePackages = { "com.example.scopetest" })
public class ScopeConfig {

private Integer counter = new Integer(0);

@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Number counter() {
counter = new Integer(counter.intValue() + 1);
return counter;
}


/* Adding a org.springframework.social.facebook.api.Facebook request-scoped bean as a real-world example why all this matters
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public Facebook facebook() {
Connection<Facebook> facebook = connectionRepository()
.findPrimaryConnection(Facebook.class);
return facebook != null ? facebook.getApi() : new FacebookTemplate();
}
*/

...................

}

Controller 文件

package com.example.scopetest;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.FacebookProfile;
import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ScopeTestController {

//@Inject
//private Facebook facebook;

@Inject
private Number counter;

private static final Logger logger = LoggerFactory
.getLogger(ScopeTestController.class);

@RequestMapping(value = "/scopetestnormal")
public void scopetestnormal() {
logger.debug("About to interact with a request-scoped bean from HTTP request thread");
logger.debug("counter is: {}", counter);

/*
* The following also works
* FacebookProfile profile = facebook.userOperations().getUserProfile();
* logger.debug("Facebook user ID is: {}", profile.getId());
*/
}



@RequestMapping(value = "/scopetestthread")
public void scopetestthread() {
logger.debug("About to spawn a new thread");
new Thread(new RequestScopedBeanAccessingThread()).start();
logger.debug("Spawned a new thread");
}


private class RequestScopedBeanAccessingThread implements Runnable {

@Override
public void run() {
logger.debug("About to interact with a request-scoped bean from another thread. Doomed to fail.");
logger.debug("counter is: {}", counter);

/*
* The following is also doomed to fail
* FacebookProfile profile = facebook.userOperations().getUserProfile();
* logger.debug("Facebook user ID is: {}", profile.getId());
*/
}

}

}
<小时/>

基于 CGLIB 的请求范围 bean 的堆栈跟踪 (proxyMode = ScopedProxyMode.TARGET_CLASS)

SLF4J: Failed toString() invocation on an object of type [$java.lang.Number$$EnhancerByCGLIB$$45ffcde7]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.counter': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:342)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.getTarget(Cglib2AopProxy.java:654)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:605)
at $java.lang.Number$$EnhancerByCGLIB$$45ffcde7.toString(<generated>)
at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:304)
at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:276)
at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:230)
at ch.qos.logback.classic.spi.LoggingEvent.<init>(LoggingEvent.java:114)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:447)18:09:48.276 container [Thread-16] DEBUG c.g.s.c.c.god.ScopeTestController - counter is: [FAILED toString()]

at ch.qos.logback.classic.Logger.filterAndLog_1(Logger.java:421)
at ch.qos.logback.classic.Logger.debug(Logger.java:514)
at com.example.scopetest.ScopeTestController$RequestScopedBeanAccessingThread.run(ScopeTestController.java:58)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:40)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:328)
... 14 more
<小时/>

基于 JDK 动态代理接口(interface)的请求范围 bean 的堆栈跟踪 (proxyMode = ScopedProxyMode.INTERFACES)

Exception in thread "Thread-16" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.facebook': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:342)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:33)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at $Proxy28.userOperations(Unknown Source)
at com.example.scopetest.ScopeTestController$PrintingThread.run(ScopeTestController.java:61)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:40)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:328)
... 6 more

最佳答案

好的,阅读SimpleThreadScope中的代码Spring 附带的我认为您可以使用 InheritableThreadLocal 创建一个 SimpleInheritableThreadScope相反。

然后只需使用一些 xml 来注册您的自定义范围:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread-inherited">
<bean class="org.mael.spring.context.support.SimpleInheritableThreadScope"/>
</entry>
</map>
</property>
</bean>

这意味着当您创建具有线程继承范围的bean时,您将可以通过每个线程的副本访问该bean,并且该副本将在您的线程生成的线程中可用,即一个请求范围的 bean,可以在请求线程中生成的线程中使用。

关于spring-mvc - Spring MVC : How to use a request-scoped bean inside a spawned thread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14986519/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com