如果上面这样配置,启动服务将会报错:
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: In this case, use RequestContextListener or RequestContextFilter to expose the current request.at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-6.0.7.jar:6.0.7]
该错误的原因就是你在一个单例bean中注入一个request作用域的bean,而request作用域bean的生命周期是在一个web请求开始创建的,所以这里你当然是没法注入的 。
解决办法:
- @Scope设置代理模式
@Component@Scope(value = https://www.isolves.com/it/cxkf/jiagou/2024-01-05/"request", proxyMode = ScopedProxyMode.TARGET_CLASS)public class Person {}
测试结果ScopeController: com.pack.scopes.Person@106a9684 - 275420804PersonService: com.pack.scopes.Person@106a9684 - 275420804ScopeController: com.pack.scopes.Person@64396678 - 1681483384PersonService: com.pack.scopes.Person@64396678 - 1681483384
每次请求接口都获取的不是同一个实例 。并且在一个完整的请求中获取的Person都是同一个 。- 使用@RequestScope
@Scope(WebApplicationContext.SCOPE_REQUEST)public @interface RequestScope {@AliasFor(annotation = Scope.class)// 设置好了使用代理ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;}
2.4 会话(session)@Component@Scope(value = https://www.isolves.com/it/cxkf/jiagou/2024-01-05/"session", proxyMode = ScopedProxyMode.TARGET_CLASS)// 与request一样,必须设置代理模式或者使用下面这个注解// @SessionScopepublic class Person {}
测试ScopeController: com.pack.scopes.Person@2b56038d - 727057293PersonService: com.pack.scopes.Person@2b56038d - 727057293ScopeController: com.pack.scopes.Person@2b56038d - 727057293PersonService: com.pack.scopes.Person@2b56038d - 727057293
多次访问都是同一个session;你再换个浏览器访问ScopeController: com.pack.scopes.Person@1aa201fd - 446824957PersonService: com.pack.scopes.Person@1aa201fd - 446824957ScopeController: com.pack.scopes.Person@1aa201fd - 446824957PersonService: com.pack.scopes.Person@1aa201fd - 446824957
此时对象就是一个新的了,不同的浏览器访问当然不是同一个session了 。2.5 应用(application)
@Scope(value = https://www.isolves.com/it/cxkf/jiagou/2024-01-05/"application", proxyMode = ScopedProxyMode.TARGET_CLASS)// @ApplicationScope// 都是web环境,所以情况都一样public class Person {}
测试360浏览器
ScopeController: com.pack.scopes.Person@6371b4b6 - 1668396214PersonService: com.pack.scopes.Person@6371b4b6 - 1668396214
Chrome浏览器ScopeController: com.pack.scopes.Person@6371b4b6 - 1668396214PersonService: com.pack.scopes.Person@6371b4b6 - 1668396214
他们是同一个对象 , application作用域生命周期与整个应用一样 , 只有你关闭了服务器,在启动后才会是再重新创建的bean对象 。3. web作用域原理3.1 注册作用域
public abstract class AbstractApplicationContext {public void refresh() {postProcessBeanFactory(beanFactory);}}public class AnnotationConfigServletWebServerApplicationContext {protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.postProcessBeanFactory(beanFactory);}}public class ServletWebServerApplicationContext {protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {// ...registerWebApplicationScopes();}private void registerWebApplicationScopes() {WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());}}public abstract class WebApplicationContextUtils {public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {registerWebApplicationScopes(beanFactory, null);}public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,@Nullable ServletContext sc) {// 注册作用域beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());if (sc != null) {ServletContextScope appScope = new ServletContextScope(sc);beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);}}}
这里每一种web作用域都有一个对应的Scope实现RequestScope,SessionScope,ServletContextScope 。
推荐阅读
- Spring Boot Starter的原理
- Spring 七种事务传播性介绍
- 摩飞便携榨汁杯体验
- 简易版的SpringBoot是如何实现的!!!
- 钓鱼饵料指南:各种饵料特点与使用技巧
- 各种钢材的尺寸与重量大全
- 网络用语有那些各指什么意思 各种网络用词的意思
- Spring非常实用的技巧,你确定知道?
- 当年一瓶雪花膏闯天下,现在护肤用的各种水都是智商税吗?
- Java Lambda 表达式各种用法,你都会了吗