Java 如何仅在web请求中@Autowire RequestScope bean
最近,我了解到RequestScope bean在web事务之外是不可用的 问题是,在web事务之外,我不想使用该bean,而不是出现错误 我怎样才能做到这一点 使用请求范围bean的组件:Java 如何仅在web请求中@Autowire RequestScope bean,java,spring,spring-boot,dependency-injection,Java,Spring,Spring Boot,Dependency Injection,最近,我了解到RequestScope bean在web事务之外是不可用的 问题是,在web事务之外,我不想使用该bean,而不是出现错误 我怎样才能做到这一点 使用请求范围bean的组件: @Component public class JavaComponent { @Autowired private RequestScopedBean requestScopedBean; @Override public void doStuff() {
@Component
public class JavaComponent {
@Autowired
private RequestScopedBean requestScopedBean;
@Override
public void doStuff() {
// TODO if in web transaction, use RequestScopedBean , otherwhise don't
}
}
豆子:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {
public String getInfo() {
return "information about the web transaction";
}
}
编辑:尝试在web请求之外使用JavaComponent时出现的错误是:
org.springframework.beans.factory.BeanCreationException:错误
正在创建名为“JavaComponent.requestScopedBean”的bean:范围
对于当前线程,“请求”未处于活动状态;考虑定义一个
如果您打算从一个目录引用此bean,则此bean的作用域代理
独生子女;嵌套异常为java.lang.IllegalStateException:否
找到线程绑定请求:您是指请求属性吗
在实际web请求之外,或在外部处理请求
最初的接收线程?如果你实际上是在
当您收到web请求并且仍然收到此消息时,您的代码可能是
在DispatcherServlet/DispatcherPortlet之外运行:在这种情况下,
使用RequestContextListener或RequestContextFilter公开
当前请求
在web请求线程之外使用bean的方法是让@Async方法在单独的线程中运行。Autowire
ApplicationContext
仅查找请求范围的bean,然后执行空检查
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
@Service
public class TestService {
@Autowired
private ApplicationContext applicationContext;
public void myMethod() {
RequestScopedBean bean = applicationContext.getBean(RequestScopedBean.class);
if (bean != null) {
// do stuff
}
}
}
我提出了一个更好的解决方案,因为applicationContext.getBean()在调用时会抛出一个异常,相反,最好检查当前线程是否在web请求上下文中执行,然后获取bean 我还测试了性能,get bean非常快(0ms),可能是因为请求范围的bean非常轻
/**
* The Class AuditConfig.
*/
@Component
public class AuditConfig implements AuditorAware<String> {
/**
* The Constant SYSTEM_ACCOUNT.
*/
public static final String SYSTEM_ACCOUNT = "system";
@Autowired
private ApplicationContext context;
/**
* Gets the current auditor.
*
* @return the current auditor
*/
@Override
public Optional<String> getCurrentAuditor() {
return Optional.ofNullable(getAlternativeUser());
}
private String getAlternativeUser() {
try {
// thread scoped context has this != null
if (RequestContextHolder.getRequestAttributes() != null) {
Object userBean = context.getBean(AuditRequestScopedBean.BEAN_NAME);
if (StringUtils.isNotBlank(((AuditRequestScopedBean) userBean).getUser()))
{
return ((AuditRequestScopedBean) userBean).getUser();
}
}
} catch (Exception e) {
return SYSTEM_ACCOUNT;
}
return SYSTEM_ACCOUNT;
}
}
/**
*类AuditConfig。
*/
@组成部分
公共类AuditConfig实现AuditorAware{
/**
*常量系统是一个帐户。
*/
公共静态最终字符串SYSTEM\u ACCOUNT=“SYSTEM”;
@自动连线
私有应用程序上下文上下文;
/**
*获取当前审计员。
*
*@返回当前审计员
*/
@凌驾
公共可选getCurrentAuditor(){
返回可选的.ofNullable(getAlternativeUser());
}
私有字符串getAlternativeUser(){
试一试{
//线程作用域上下文具有此!=null
if(RequestContextHolder.getRequestAttributes()!=null){
Object userBean=context.getBean(AuditRequestScopedBean.BEAN\u名称);
if(StringUtils.isNotBlank(((AuditRequestScopedBean)userBean).getUser())
{
return((AuditRequestScopedBean)userBean.getUser();
}
}
}捕获(例外e){
返回系统账户;
}
返回系统账户;
}
}
您遇到了什么错误?另外,在Web请求的上下文之外使用JavaComponent
的用例是什么?我已经用您的问题的答案编辑了这个问题。谢谢这回答了你的问题吗?不,我不想在异步请求中使用请求范围的bean,我只想在web请求之外不使用它。我理解这一点。使用proxyMode
(如其中一个答案所示)将防止出现错误。这意味着您现在可以正确初始化bean。关于异步请求,您应该能够在运行时处理缺少的请求范围