scope
在 Spring 框架中,Bean 的 Scope(作用域)用于确定 Spring 容器如何创建和管理 Bean的实例。在 Spring 中可以使用@Scope注解来实现。
常见的作用域有以下:
singleton:一个 Spring 容器只有这一个 Bean 实例,singleton是 Spring 的默认值。prototype:使得 Bean 在每次调用时都会重新实例化(这时destroy方法不生效)。request:Web 项目中,Bean 实例存活于一个 Request 请求。session:Web 项目中,Bean 实例存活于一次 Session 中。global-session:只在 protal 应用中使用,给每一个global http session 创建一个 Bean 实例。
singleton
singleton 作用域的 Bean,在 Spring IoC 容器中就有且仅有一个该类型的实例对象,也就是单例的。下面用一个例子来说明。
- 编写一个
SingletonService类,它的scope为singleton。
@Service
@Scope("singleton")
public class SingletonService {
}
- 用一个配置类来加载组件。
@Configuration
@ComponentScan("com.test")
public class ScopeConfig {
}
- 首先验证一个 Spring 容器下 context 分别获取两个 Bean 是相同的。
public class ScopeMain {
public static void main(String[] args){
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ScopeConfig.class);
SingletonService s1 = context.getBean(SingletonService.class);
SingletonService s2 = context.getBean(SingletonService.class);
System.out.println(s1.equals(s2));
context.close();
}
}
- 以下的情况实例化了两个 Spring 容器,则输出为 false。
public class ScopeMain {
public static void main(String[] args){
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ScopeConfig.class);
AnnotationConfigApplicationContext context2 =
new AnnotationConfigApplicationContext(ScopeConfig.class);
SingletonService s1 = context.getBean(SingletonService.class);
SingletonService s2 = context2.getBean(SingletonService.class);
System.out.println(s1.equals(s2));
context.close();
}
}
prototype
prototype 作用域的 Bean,就是 “非单例” 的,每次请求获取该 Bean 时,都会创建一个新的实例。下面用一个例子来说明。
- 编写一个
PrototypeService类,它的scope为prototype。
@Service
@Scope("prototype")
public class PrototypeService {
}
- 用一个配置类来加载组件。
@Configuration
@ComponentScan("com.test")
public class ScopeConfig {
}
- 在一个 Spring 容器下 context 分别获取两个 Bean 是不相同的。
public class ScopeMain {
public static void main(String[] args){
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ScopeConfig.class);
PrototypeService p1 = context.getBean(PrototypeService.class);
PrototypeService p2 = context.getBean(PrototypeService.class);
System.out.println(p1.equals(p2));
context.close();
}
}
singleton、prototype 区分总结
在 Spring 容器中 Bean 的作用域(Scope)有singleton和prototype。
对于singleton,其对象为单例模式,这样对象在 Spring 容器中只维持这一个,需要的时候向 Spring 获取,意即对象的控制权交给了 Spring 容器,对象的初始化(创建)与销毁取决于 Spring 容器(单例模式的对象在Spring 容器加载时创建;关闭时销毁)而不是 Bean 类本身。
对于prototype,则不完全交给 Spring 容器管理,初始化(创建)时交由 Spring 容器,但销毁时不取决于Spring 容器,其销毁在于客户端。客户端访问时由 Spring 创建对象,客户端访问完成后,Bean 对象处于未引用的状态下,就会被 JVM 自动回收。