SpringBoot单例@Component中如何使用Request Scope对象?
解决单例组件中使用请求作用域对象的问题
你不需要在所有方法里传递参数,Spring提供了两种常用方案来实现单例组件中安全使用请求作用域的对象:
方案一:创建请求作用域的持有类(推荐)
创建一个专门的请求作用域bean来持有myObject,Spring会自动为这个bean生成代理,确保单例组件每次调用都能获取当前请求的实例。
步骤1:定义请求作用域的持有类
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; @Component @Scope( value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS ) public class MyRequestScopedHolder { private MyClass myObject; public MyClass getMyObject() { return myObject; } public void setMyObject(MyClass myObject) { this.myObject = myObject; } }
步骤2:修改单例组件注入持有类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MyComponent { @Autowired private MyBC myBC; @Autowired private MyRequestScopedHolder requestHolder; public void method1(MyClass param) { requestHolder.setMyObject(param); method2(); } public void method2() { System.out.println(requestHolder.getMyObject()); } }
说明:proxyMode = ScopedProxyMode.TARGET_CLASS是关键,Spring会生成CGLIB代理类,单例的MyComponent注入的是代理对象,每次调用requestHolder的方法时,代理会从当前请求上下文获取真实的持有类实例,保证每个请求的myObject相互独立。
方案二:使用RequestContextHolder直接操作请求属性
如果不想额外创建类,可以借助Spring的RequestContextHolder直接把对象存在请求作用域中:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @Component public class MyComponent { @Autowired private MyBC myBC; public void method1(MyClass param) { // 将对象存入当前请求属性 RequestContextHolder.getRequestAttributes() .setAttribute("myObject", param, RequestAttributes.SCOPE_REQUEST); method2(); } public void method2() { // 从当前请求属性中取出对象 MyClass myObject = (MyClass) RequestContextHolder.getRequestAttributes() .getAttribute("myObject", RequestAttributes.SCOPE_REQUEST); System.out.println(myObject); } }
说明:RequestContextHolder会绑定当前线程的请求上下文,所以并发场景下每个请求的属性互不干扰,但这种方式代码耦合Spring API,适合简单场景。
内容的提问来源于stack exchange,提问作者tpcordeiro
相关产品推荐
相关产品推荐

