Spring Bean 作用域

    技术2026-01-01  5

    分类

    在我们写 xxx.xml 文件此 Spring 配置文件时,其中 <bean> 标签中有一个 scope 属性,这个属性指定了对象的作用范围。具体如下:

    类型说明singleton默认值,在 Spring 容器中仅存在一个 Bean 实例, Bean 以单实例的方式存在;prototype每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 get Bean () 时,相当于执行 new Xxx Bean () 操作。request每次 HTTP 请求都会创建一个新的 Bean ,该 Bean 仅在当前HTTP request 内有效,此作用域仅适用于 WebApplicationContext 环境。session每次 HTTP 请求都会创建一个新的 Bean ,该 Bean 仅在当前 HTTP Session 内有效。此作用域仅适用于 WebApplicationContext 环境。同一个 HTTP Session 共享一个 Bean ,不同的 HTTP Session 使用不同的 Bean 。globalSession类似于上者,但是只应用在 Portlet 环境。如果没有 Portlet 环境那么 globalSession 相当于 session。此作用域仅适用于 WebApplicationContext 环境。

    详解

    singleton

    单例作用域:当一个 Bean 的作用域为 singleton,那么Spring 容器中只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,则只会返回 Bean 的同一实例。 singleton 是单例类型,即在创建起容器时就同时自动创建了一个 Bean 的对象,不管你是否使用。我们可以指定 Bean 节点的 lazy-init=”true” 来延迟初始化 Bean ,这时候,只有在第一次获取 Bean 时才会初始化 Bean ,即第一次请求该 Bean 时才初始化。 每次获取到的对象都是同一个对象。

    配置方式:

    XML:<bean id="ServiceImpl" class="com.mindartisan.service.ServiceImpl" scope="singleton"> <bean id="ServiceImpl" class="com.mindartisan.service.ServiceImpl" singleton="true"/> 使用注解 @Scope("singleton"):@Service @Scope("singleton") public class ServiceImpl{ …… }

    prototype

    原型作用域:当一个 Bean 的作用域为 prototype 时,表示一个 Bean 定义对应过个对象实例。每次程序对 Bean 进行请求时,都会创建一个新的 Bean 实例。它在我们创建容器的时候并没有实例化,而是当我们获取的时候才会去创建一个对象,并且每次获取到的对象不是同一个对象。

    配置方式:

    XML:<bean id="ServiceImpl" class="com.mindartisan.service.ServiceImpl" scope="prototype"/> <bean id="ServiceImpl" class="com.mindartisan.service.ServiceImpl" singleton="false"/> 使用注解 @Scope("prototype"):@Service @Scope("prototype") public class ServiceImpl{ …… }

    request

    每次 HTTP 请求调用 car Bean 时,Spring 容器会自动创建一个新的 car Bean。

    配置方式:

    XML:<bean id="car" class="com.mindartisan.car" scope="request"/> 使用注解 @Scope("request") 或 @RequestScope

    session

    car Bean 的作用域将横跨整个 HTTP Session,Session 中的所有 HTTP 请求都共享一个 car Bean。

    XML:<bean id="car" class="com.mindartisan.car" scope="session"/> 使用注解 @Scope("session") 或 @SessionScope

    globalSession

    类似于 session 作用域,不过仅在 Portlet(类似于 Servlet? 只知道是比较早的技术) 的 Web 应用中使用。Portlet 规范定义了全局 Session 的概念,它被组成 Portlet Web 应用的所有子 Portlet 共享。如果不在 Portlet Web 应用环境下,那么 globalSession 作用域等价于 session 作用域。

    基于 XML 的配置方式:

    <bean id="car" class="com.mindartisan.car" scope="globalSession"/>

    singleton 与 prototype 区别

    对于 singleton 作用域的 Bean 来说,每次请求该 Bean 都将获得相同的实例;对于 prototype 作用域的 Bean 来说,每次请求该 Bean 都会创建一个新的 Bean 实例。

    生命周期:

    类型对象出生对象活着对象死亡singleton应用加载,容器被创建时对象创建容器在,对象在销毁容器时,对象销毁prototype使用对象时创建新的对象对象被使用就一直活着长时间不用,被 GC 回收

    选用:

    无状态的 Bean、需要耗费大量资源的 Bean(数据库连接)、在整个应用中缓存和共享数据的 Bean、需要有序受控制的关闭程序时使用 singleton;有状态的 Bean 使用 prototype。

    有状态对象(Stateful Bean) : 就是有实例变量的对象,可以保存数据,是 非线程安全 的。每个用户有自己特有的一个实例,在用户的生存期内,bean 保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean 的生命期也告结束。即每个用户最初都会得到一个初始的 bean。 无状态对象(Stateless Bean): 就是没有实例变量的对象,不能保存数据,是不变类,是 线程安全 的。bean 一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态 bean。但无状态会话 bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。

    参考

    Bean Scopes 作用域

    Spring容器中Bean的作用域

    Prototype vs Singleton Spring Beans - How-to, Differences and Uses

    《精通 Spring 4.x 企业应用开发实战》

    Processed: 0.012, SQL: 9