在春季4坚持这一点,可能与5相同。
所以,我有什么
@RequestScope
@Component
public class APIAction { ... }
private final ObjectProvider<APIAction> apiAction;
apiAction.getIfAvailable()...
null
,异常或其他东西。相反,我收到了一些不能测试为null的代理对象,或者任何表明bean确实可用的状态。如果我尝试调用任何bean方法,我都会得到异常提示,最后说访问绑定到Web请求的线程之外的bean。问题是,我使用错了吗?现在,我正在通过调用此命令RequestContextHolder.getRequestAttributes() != null
来检查访问bean之前的请求范围,这确实很丑陋,而且我需要所有时间告诉人们为什么应该这样使用它。
还有一个问题是,实际上可以在没有请求绑定的情况下在线程中实例化该bean吗?
答案 0 :(得分:1)
TL; DR::您不能使用ObjectProvider.getIfAvailable()
来检查是否在请求范围内。
改为使用if (RequestContextHolder.getRequestAttributes() != null)
。
ObjectProvider
的Javadoc说:
ObjectFactory
的一种变体,专门为注射点设计,允许程序化的可选性和宽大的非唯一处理。
对于单例bean,ObjectProvider<APIAction>
是@Autowired(required = false) List<APIAction>
的替代方法,其方法可以更好地表示目的。
对于原型bean,它允许按需创建原型,包括可选的构造函数参数。
但是,这完全取决于bean的存在性,即关于bean是否已注册(以及注册了多少)。组件扫描会注册任何@Component
(或其他)带注释的类,而与bean的 scope 无关。
@RequestScope
bean存在,因此代码可以更改为@Autowired private final APIAction apiAction;
,并且始终为非null。
apiAction
所引用的对象是一个代理,这一事实除了要点之外,还将根据请求上下文将方法调用应用于不同的实例。
调用APIAction
方法时,您会得到IllegalStateException
的话:
未找到线程绑定的请求:您是在实际Web请求之外引用请求属性,还是在原始接收线程之外处理请求?如果您实际上是在Web请求中操作并且仍然收到此消息,则您的代码可能在DispatcherServlet外部运行:在这种情况下,请使用RequestContextListener或RequestContextFilter公开当前请求。
在内部,一个带注释的@RequestScope
类具有一个RequestScope
类型的Scope
,并且Javadoc说:
依赖于线程绑定的
RequestAttributes
实例。
它通过调用RequestContextHolder.currentRequestAttributes()
来执行此操作,这会引发上述异常。
解决方案::要检查您是否处于请求上下文中,请调用RequestContextHolder.getRequestAttributes()
并检查null
的返回值。