在 Spring 框架中,Bean 是构成应用程序的重要组成部分。Spring 容器负责管理这些 Bean 的生命周期和配置。为了满足不同场景的需求,Spring 提供了多种 Bean 作用域(scope),即 Bean 在容器中的生命周期和可见范围。本文将详细介绍 Spring Bean 的作用域及其应用场景。
一、什么是 Bean 作用域
Bean 作用域定义了 Bean 在 Spring 容器中的生命周期和可见范围。不同的作用域决定了 Bean 的创建时机、存储位置和销毁时机。Spring 提供了几种常用的 Bean 作用域,每种作用域都有其特定的使用场景。
二、常见的 Bean 作用域
Spring 提供了五种主要的 Bean 作用域:
singleton
prototype
request
session
application
1. Singleton
singleton
是默认的作用域。在这种作用域下,Spring 容器在应用启动时创建一个唯一的 Bean 实例,并在整个应用的生命周期内共享该实例。无论你注入多少次,该 Bean 实例都是同一个。
特点:
- 适用于无状态的服务和工具类。
- 节省内存资源,因为所有请求共享一个实例。
示例:
java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("singleton")
public class SingletonBean {
// Bean logic here
}
2. Prototype
prototype
作用域表示每次请求都会创建一个新的 Bean 实例。它适用于需要频繁创建和销毁的有状态对象。
特点:
- 适用于有状态的对象,例如用户会话。
- 每次请求都会创建新的实例,消耗更多内存。
示例:
java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class PrototypeBean {
// Bean logic here
}
3. Request
request
作用域专门用于 Web 应用程序。在这种作用域下,每个 HTTP 请求都会创建一个新的 Bean 实例,并在请求结束时销毁该实例。
特点:
- 适用于 Web 应用中的控制器和服务类。
- 每个 HTTP 请求都有独立的实例。
示例:
java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("request")
public class RequestBean {
// Bean logic here
}
4. Session
session
作用域也用于 Web 应用程序。在这种作用域下,每个 HTTP 会话(session)都会创建一个新的 Bean 实例,并在会话结束时销毁该实例。
特点:
- 适用于需要在用户会话期间保持状态的对象。
- 每个 HTTP 会话有独立的实例。
示例:
java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("session")
public class SessionBean {
// Bean logic here
}
5. Application
application
作用域表示在 ServletContext 的生命周期内共享一个 Bean 实例。它适用于整个 Web 应用程序范围内共享状态的 Bean。
特点:
- 适用于需要在整个 Web 应用程序中共享的对象。
- 作用范围是整个 ServletContext。
示例:
java
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("application")
public class ApplicationBean {
// Bean logic here
}
三、自定义作用域
除了上述内置作用域外,Spring 还允许开发者定义自定义作用域。自定义作用域需要实现 Scope
接口,并注册到 Spring 容器中。
示例:
java
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import java.util.HashMap;
import java.util.Map;
public class CustomScope implements Scope {
private final Map<String, Object> scopedObjects = new HashMap<>();
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
return scopedObjects.computeIfAbsent(name, k -> objectFactory.getObject());
}
@Override
public Object remove(String name) {
return scopedObjects.remove(name);
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
// Not implemented for this example
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return "custom";
}
}
注册自定义作用域:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.SimpleThreadScope;
@Configuration
public class AppConfig {
@Bean
public CustomScope customScope() {
return new CustomScope();
}
}
四、总结
Spring 提供了多种 Bean 作用域,以满足不同应用场景的需求。通过合理选择和配置 Bean 作用域,可以优化应用程序的性能和资源管理。无论是单例 Bean 还是原型 Bean,还是用于 Web 应用的请求和会话作用域,都有其特定的应用场景。