Spring Bean 的作用域

在 Spring 框架中,Bean 是构成应用程序的重要组成部分。Spring 容器负责管理这些 Bean 的生命周期和配置。为了满足不同场景的需求,Spring 提供了多种 Bean 作用域(scope),即 Bean 在容器中的生命周期和可见范围。本文将详细介绍 Spring Bean 的作用域及其应用场景。

一、什么是 Bean 作用域

Bean 作用域定义了 Bean 在 Spring 容器中的生命周期和可见范围。不同的作用域决定了 Bean 的创建时机、存储位置和销毁时机。Spring 提供了几种常用的 Bean 作用域,每种作用域都有其特定的使用场景。

二、常见的 Bean 作用域

Spring 提供了五种主要的 Bean 作用域:

  1. singleton
  2. prototype
  3. request
  4. session
  5. 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 应用的请求和会话作用域,都有其特定的应用场景。

相关推荐
余炜yw1 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
攸攸太上2 分钟前
JMeter学习
java·后端·学习·jmeter·微服务
Kenny.志5 分钟前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端
不修×蝙蝠7 分钟前
八大排序--01冒泡排序
java
sky丶Mamba22 分钟前
Spring Boot中获取application.yml中属性的几种方式
java·spring boot·后端
数据龙傲天1 小时前
1688商品API接口:电商数据自动化的新引擎
java·大数据·sql·mysql
带带老表学爬虫1 小时前
java数据类型转换和注释
java·开发语言
千里码aicood1 小时前
【2025】springboot教学评价管理系统(源码+文档+调试+答疑)
java·spring boot·后端·教学管理系统
彭于晏6892 小时前
Android广播
android·java·开发语言
程序员-珍2 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发