Spring Bean 的作用域

发布于:2024-06-23 ⋅ 阅读:(25) ⋅ 点赞:(0)

在 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 实例都是同一个。

特点:

  • 适用于无状态的服务和工具类。
  • 节省内存资源,因为所有请求共享一个实例。

示例:

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class SingletonBean {
    // Bean logic here
}

2. Prototype

prototype 作用域表示每次请求都会创建一个新的 Bean 实例。它适用于需要频繁创建和销毁的有状态对象。

特点:

  • 适用于有状态的对象,例如用户会话。
  • 每次请求都会创建新的实例,消耗更多内存。

示例:

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 请求都有独立的实例。

示例:

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 会话有独立的实例。

示例:

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。

示例:

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("application")
public class ApplicationBean {
    // Bean logic here
}

三、自定义作用域

除了上述内置作用域外,Spring 还允许开发者定义自定义作用域。自定义作用域需要实现 Scope 接口,并注册到 Spring 容器中。

示例:

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";
    }
}

注册自定义作用域:

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 应用的请求和会话作用域,都有其特定的应用场景。