java – Spring @Async不允许使用autowired bean
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – Spring @Async不允许使用autowired bean,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5748字,纯文字阅读大概需要9分钟。
内容图文
![java – Spring @Async不允许使用autowired bean](/upload/InfoBanner/zyjiaocheng/825/3ed31fc0627940b0af4d797625a95ae6.jpg)
参见英文答案 > Accessing HttpSession outside of the originally receiving thread 1个
我有一个完全注释驱动的Spring Boot 1.3.5应用程序,它有这个异步服务需要自动装配另一个服务bean(并且将来它需要自动装配一个存储库bean,但我还没有)按顺序执行一些业务逻辑:
@Service
public class AsyncService {
@Autowired
public HelpingService helpingService;
@Async
public Future<String> doFoo(String someArgument)
throws InterruptedException {
Thread.sleep(3000);
System.out.println("about to do Foo "+someArgument);
String result = "";
try {
result = helpingService.getSomeStuff(someArgument);
}
catch (Exception e) {
e.printStackTrace();
}
return new AsyncResult<String>(hello);
}
}
上面的方法是从@Controller bean调用的,它有其他端点(非异步),它们也按预期工作
@Controller
public class MyController extends BaseController {
@Autowired
HelpingService helpingService;
@Autowired
AsyncService asyncService;
@RequestMapping(method=RequestMethod.GET, value={"/rest/threads/getIp/{jobId}"}, produces={"application/json"})
public ResponseEntity<?> getLog(@PathVariable("jobId") String jobId) throws InterruptedException {
asyncService.doFoo(jobId);
return new ResponseEntity<>(HttpStatus.OK);
}
}
这里是帮助服务的实现(它是一个接口),当我没有从上面的@Async方法执行时,调用任何方法都可以正常工作:
@Service
@Validated
public class HelpingServiceImpl implements HelpingService {
@Autowired
HttpSession httpSession;
@Value(value="${projName}")
private String projName;
public String getServerAddress(){
AuthRegion region = (AuthRegion) httpSession.getAttribute("region");
if (region != null)
return region.getServerAddress();
else
return null;
}
@Override
public String getSomeStuff(String jobId) {
String responseString = "";
String projName = this.projName;
String serverAddress = getServerAddress(); // Code stops here with an exception
// Some code here that works fine outside this thread
return responseString;
}
}
这是被捕获的例外:
about to do Foo (267)
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.support.WebApplicationContextUtils.currentRequestAttributes(WebApplicationContextUtils.java:309)
at org.springframework.web.context.support.WebApplicationContextUtils.access$400(WebApplicationContextUtils.java:64)
at org.springframework.web.context.support.WebApplicationContextUtils$SessionObjectFactory.getObject(WebApplicationContextUtils.java:366)
at org.springframework.web.context.support.WebApplicationContextUtils$SessionObjectFactory.getObject(WebApplicationContextUtils.java:361)
at org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke(AutowireUtils.java:307)
at com.sun.proxy.$Proxy96.getAttribute(Unknown Source)
at corp.fernandopcg.myapp.service.ThreadServiceImpl.getRundeckServerPort(ThreadServiceImpl.java:45)
at corp.fernandopcg.myapp.service.ThreadServiceImpl.getJobExecutionOutput(ThreadServiceImpl.java:65)
at corp.fernandopcg.myapp.service.AsyncService.doFoo(AsyncService.java:40)
at corp.fernandopcg.myapp.service.AsyncService$$FastClassBySpringCGLIB$$7e164220.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:115)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
我添加了(由于我无法在SpringBootServletInitializer的同时扩展AsyncConfigurer,并且我不得不捕获一个不提及的异常),我的Application主类的taskExecutor部分如下所示,由this tutorial引导,看起来类似于在我看来,我需要什么
@SpringBootApplication
@EnableAsync
@EnableJpaRepositories(repositoryFactoryBeanClass = DataTablesRepositoryFactoryBean.class)
public class MyApplication extends SpringBootServletInitializer implements AsyncConfigurer{
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("SomeRandomLookup-");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
// TODO Auto-generated method stub
return null;
}
}
我可以告诉我的@Async服务能够使用该应用程序的其他服务吗?因为如果那是不可能的,我真的没有看到这些线程机制的使用.
解决方法:
这很好地说明了请求范围注入可能存在问题的原因.你的HelpingServiceImpl对特定于请求的HttpSession有一个隐藏的依赖,它看起来像一个字段,但实际上是Spring在每次调用时解析的代理,总是引用“当前”请求(使用线程局部变量).
问题在于,通过调用@Async,您将HelpingServiceImpl调用与触发它的请求分开,并且不再存在允许它从全局上下文中提取信息的同一线程上的隐式连接.
最直接的解决方法是使您的依赖项显式化 – 而不是让您的HelpingServiceImpl直接从HttpSession中获取区域,将该区域作为方法参数传递给它.
内容总结
以上是互联网集市为您收集整理的java – Spring @Async不允许使用autowired bean全部内容,希望文章能够帮你解决java – Spring @Async不允许使用autowired bean所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。