Scope作用域
一. Scope属性类型
主要有以下六种:
① singleton(单例模式)- 默认值
-
含义:在整个 Spring IoC 容器中,只存在一个该 Bean 的实例。
-
生命周期:容器启动时创建(如果设置为懒加载则在第一次获取时创建),容器关闭时销毁。
-
共享方式:所有对该 Bean 的依赖注入和查找,返回的都是同一个对象。
-
适用场景:无状态的 Bean,例如 Service、DAO、工具类等。这是最常用、最高效的作用域
② prototype(原型模式)
-
含义:每次从容器中获取该 Bean 时,都会创建一个新的实例。
-
生命周期:每次获取时创建,实例返回给调用者后,其生命周期就由调用者管理,Spring 容器不再跟踪它的后续生命周期,也不会调用它的销毁方法。
-
共享方式:每次获取到的都是不同的新对象。
-
适用场景:有状态的 Bean,每次使用都需要一个全新的、独立的对象,以避免线程安全问题。
③ request
-
含义:为每一个 HTTP 请求创建一个新的 Bean 实例。
-
生命周期:在一次 HTTP 请求开始时创建,请求结束时销毁。
-
共享方式:在一次请求内部,所有注入的地方共享同一个实例。
-
适用场景:用于存储请求相关的数据,如表单数据、请求属性等。
④ session
-
含义:为每一个 HTTP Session 创建一个新的 Bean 实例。
-
生命周期:在一个 HTTP Session 创建时创建,Session 失效时销毁。
-
共享方式:在同一个用户会话内部,所有注入的地方共享同一个实例。
-
适用场景:用于存储用户会话信息,如用户登录信息、购物车等。
⑤ application
-
含义:为整个 Web 应用创建一个 Bean 实例。注意:它和
singleton
很像,但区别在于:-
singleton
是每个 Spring 容器 一个实例(一个应用可以有多个容器)。 -
application
是每个 ServletContext 一个实例(一个应用通常只有一个)。
-
-
生命周期:Web 应用启动时创建,应用停止时销毁。
-
适用场景:用于存储全局的、应用级别的数据,其生命周期与
ServletContext
相同。
⑥ websocket
-
含义:为每一个 WebSocket 会话创建一个 Bean 实例。
-
生命周期:在 WebSocket 会话建立时创建,会话关闭时销毁。
-
适用场景:用于存储与单个 WebSocket 连接相关的状态信息。
二.单例Bean注入其它scope的场景
1.类的准备
package com.example.springdemo.demos.a26;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import javax.annotation.PreDestroy;/*** @author zhou* @version 1.0* @description TODO* @date 2025/10/14 22:17*/
@Scope("application")
@Component
public class BeanForApplication {private static final Logger log = LoggerFactory.getLogger(BeanForApplication.class);@PreDestroypublic void destroy(){log.info("destroy");}
}
package com.example.springdemo.demos.a26;import com.example.springdemo.demos.a25.Bean1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import javax.annotation.PreDestroy;/*** @author zhou* @version 1.0* @description TODO* @date 2025/10/14 22:13*/
@Scope("request")
@Component
public class BeanForRequest {private static final Logger log = LoggerFactory.getLogger(BeanForRequest.class);@PreDestroypublic void destroy(){log.info("destroy");}
}
package com.example.springdemo.demos.a26;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import javax.annotation.PreDestroy;/*** @author zhou* @version 1.0* @description TODO* @date 2025/10/14 22:15*/
@Scope("session")
@Component
public class BeanForSession {private static final Logger log = LoggerFactory.getLogger(BeanForSession.class);@PreDestroypublic void destroy(){log.info("destroy");}
}
2.MyController
package com.example.springdemo.demos.a26;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;/*** @author zhou* @version 1.0* @description TODO* @date 2025/10/14 22:18*/
@RestController
public class MyController {@Lazy@Autowiredprivate BeanForRequest beanForRequest;@Lazy@Autowiredprivate BeanForSession beanForSession;@Lazy@Autowiredprivate BeanForApplication beanForApplication;@GetMapping(value = "/test", produces = "text/html")public String test(HttpServletRequest request, HttpSession session) {ServletContext sc = request.getServletContext();String sb = "<ul>" +"<li>" + "request scope:" + beanForRequest + "</li>" +"<li>" + "session scope:" + beanForSession + "</li>" +"<li>" + "application scope:" + beanForApplication + "</li>" +"</ul>";return sb;}}
在单例Bean中注入其它Scope的Bean,必须配置@Lazy注解注入。
3.启动类
package com.example.springdemo.demos.a26;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @author zhou* @version 1.0* @description TODO* @date 2025/10/14 22:12*/
@SpringBootApplication
public class b07Application {public static void main(String[] args) {SpringApplication.run(b07Application.class,args);}
}
4.访问接口
1)刷新浏览器
BeanForRequest对象变了,其它两个对象没有变。
2)换一个浏览器
BeanForSession和BeanForRequest对象都改变了,只有BeanForApplication对象没有改变。
3)关闭容器
BeanForSession和BeanForRequest对象都被销毁并输出在控制台,但BeanForApplication的日志并没有打印。BeanForApplication在整个ServletContext容器运行期间都不会变。