💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[toc] bean在定义的时候可以指定范围,spring提供了6种范围,其中4种是web应用环境相关的. | 范围 | 说明 | | --- | --- | |singleton | 默认的,一个bean定义,只有一个对象实例 | | prototype | 一个bean定义,可以有任意对象实例 | | request | web环境下,一个bean定义,每次http请求生命周期,对应一个对象实例 | | session | web环境下,一个bean定义,每次http会话生命周期,对应一个对象实例 | | application | web环境下,一个bean定义,每次servlet上下文生命周期,对应一个对象实例 | |websocket |web环境下,一个bean定义,每次websocket请求生命周期,对应一个对象实例 | ## 1.5.1. The singleton scope 单例范围 ![singletone](https://box.kancloud.cn/a1e5415e8969df3b1fa9ab3cf9bfe7b7_800x398.png) spring的单例不同于(Gang of Four (GoF) patterns book)设计模式的单例,设计模式的单例是通过编码控制一个`ClassLoader`只创建一个类的对象实例.spring的单例则是一个容器一个bean. xml定义如下 ~~~ <bean id="accountService" class="com.foo.DefaultAccountService"/> <!-- the following is equivalent, though redundant (singleton scope is the default) --> <bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/> ~~~ ## 1.5.2. The prototype scope 原型范围,每次注入其他bean或者调用`getBean()`方法,获取的都是新的对象实例 一般的规则是,有状态的bean使用原型范围,无状态的bean使用单例范围 ![prototype](https://box.kancloud.cn/73bdfe9ece22e1ae54cfe4282664f27f_800x397.png) xml定义如下: ~~~ <bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/> ~~~ ## 1.5.3. Singleton beans with prototype-bean dependencies 如果在单例范围的bean中注入原型范围的bean,考虑注入是发生在实例化过程中的,因此,在实例化单例范围的bean时,也只有一次注入的原型范围的bean机会,所以,单例bean中的原型,其实是同一个对象, 如果想在单例bean中,每次使用的原型bean都是新的,则参考[method injection](https://docs.spring.io/spring/docs/5.0.7.RELEASE/spring-framework-reference/core.html#beans-factory-method-injection) ## 1.5.4. Request, session, application, and WebSocket scopes `request, session, application`, and` websocket`这几个范围只能在web环境中使用,例如`XmlWebApplicationContext`,如果使用其他非web环境的上下文,如`ClassPathXmlApplicationContext`,则会发生异常`IllegalStateException` ### Initial web configuration 为了能正常使用web环境下的几个范围,需要做一些初始化(单例和原型的并不需要),不同的环境有不同的初始化方式 如果是通过spring web mvc访问bean,请求会经过spring内部的`DispatcherServlet`处理,不再需要其他设置,`DispatcherServlet`已经暴露了所有的相关状态. 如果使用servlet2.5 web容器,请求会经过spring 外部的`DispatcherServlet`(例如JSF,Struts),需要注册`org.springframework.web.context.request.RequestContextListener ServletRequestListener`,对于servlet3.0,可以编码实现`WebApplicationInitializer `接口.其他,或更老的容器,添加下面的声明到`web.xm`l文件 ~~~ <web-app> ... <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> ... </web-app> ~~~ TODO