@Scope(“prototype“)

news/2025/1/20 21:00:32/

@Scope("prototype") 是 Spring 框架中用于定义 Bean 作用域的注解之一,它的主要作用是将一个 Bean 定义成 原型作用域Prototype Scope)。在原型作用域下,每次从 Spring 容器中请求这个 Bean 时,都会创建一个新的实例。


@Scope("prototype") 的作用

  1. 默认作用域:单例(Singleton Scope)
    在 Spring 中,Bean 的默认作用域是单例(@Scope("singleton")),意味着整个 Spring 容器中只会创建一个该 Bean 的实例,无论获取该 Bean 的次数有多少,都会返回同一个实例。

  2. 原型作用域(Prototype Scope)
    如果将 Bean 标记为 @Scope("prototype"),则表示该 Bean 是原型作用域。每次通过 Spring 容器获取这个 Bean 时,都会创建一个全新的实例,这与单例作用域的行为完全不同。


如何使用 @Scope("prototype")

java">import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;@Component
@Scope("prototype") // 标记为原型作用域
public class PrototypeBean {public PrototypeBean() {System.out.println("PrototypeBean instance created!");}
}

@Scope("prototype") 的生命周期

与单例作用域的 Bean 不同,原型作用域的 Bean 具有以下特点:

  1. 每次请求都会创建一个新实例

    • 无论通过调用 ApplicationContext#getBean() 方法,还是通过注入方式(例如通过 @Autowired)获取原型作用域的 Bean,每次都会创建一个全新的实例。
  2. 不受 Spring 容器的完全管理

    • Spring 容器只负责创建和返回原型作用域的 Bean,但不会对其进行后续的生命周期管理(例如,不会销毁它)。
    • 开发者需要负责清理(销毁)原型作用域的 Bean(如果需要)。
  3. 适用场景

    • 原型作用域适用于需要「短生命周期」的对象,或者需要生成多个实例的场景,例如:
      • 操作中需要临时创建对象(如一个用户操作的上下文)。
      • 在某些场景中,您需要一个特定的对象,每次使用时都需要是全新的(而不是共享的)。

对比 @Scope("singleton")@Scope("prototype")

特性单例作用域(Singleton)原型作用域(Prototype)
默认值
实例数量Spring 容器中只有一个实例每次请求都会创建一个新实例
实例管理由 Spring 容器全权负责(包括初始化和销毁)仅由 Spring 容器负责创建,不负责销毁
适用场景适用于共享的全局对象(如服务类或工具类等)适用于需要「短生命周期」或需要动态创建的对象

示例代码与行为分析

以下是一个完整示例,演示 @Scope("prototype") 的作用:

PrototypeBean 类
java">import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;@Component
@Scope("prototype")
public class PrototypeBean {public PrototypeBean() {System.out.println("PrototypeBean instance created!");}
}
SingletonBean 类
java">import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class SingletonBean {@Autowiredprivate PrototypeBean prototypeBean1;public void showPrototypeBean() {System.out.println("PrototypeBean instance: " + prototypeBean1);}
}
主方法
java">import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestApp {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext("com.example");// 第一次获取 SingletonBeanSingletonBean singletonBean1 = context.getBean(SingletonBean.class);singletonBean1.showPrototypeBean();// 第二次获取 SingletonBeanSingletonBean singletonBean2 = context.getBean(SingletonBean.class);singletonBean2.showPrototypeBean();// 手动获取 PrototypeBeanPrototypeBean prototypeBean1 = context.getBean(PrototypeBean.class);PrototypeBean prototypeBean2 = context.getBean(PrototypeBean.class);System.out.println("PrototypeBean instances comparison: " + (prototypeBean1 == prototypeBean2)); // false}
}
输出结果
PrototypeBean instance created!
PrototypeBean instance: com.example.PrototypeBean@1a2b3c4
PrototypeBean instance: com.example.PrototypeBean@1a2b3c4
PrototypeBean instance created!
PrototypeBean instance created!
PrototypeBean instances comparison: false

分析:

  1. PrototypeBean 的实例在 Spring 容器初始化时并未被创建(不同于单例作用域)。
  2. 每次调用 context.getBean(PrototypeBean.class) 时都会创建一个新实例。
  3. 如果将一个原型作用域的 Bean 注入到单例作用域的 Bean 中,Spring 容器只会注入 一个实例(因为依赖注入通常发生在容器启动时),后续不会动态更新。

在原型作用域中动态获取实例

如果您需要在运行时动态获取新的原型实例,可以通过以下方式解决:

  1. 使用 @Lookup 注解
    在单例作用域的 Bean 中通过 @Lookup 动态注入原型实例(如之前的例子)。

  2. 手动调用 ApplicationContext#getBean()
    手动从容器中获取新的原型实例。

  3. 使用 ObjectFactoryProvider
    通过 ObjectFactoryjavax.inject.Provider 提供动态获取实例的能力。

示例(使用 ObjectFactory):

java">import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class SingletonBean {@Autowiredprivate ObjectFactory<PrototypeBean> prototypeBeanFactory;public void showPrototypeBean() {PrototypeBean prototypeBean = prototypeBeanFactory.getObject(); // 获取一个新的 PrototypeBean 实例System.out.println("PrototypeBean instance: " + prototypeBean);}
}

总结

  • @Scope("prototype") 意味着每次请求都会创建一个新的 Bean 实例。
  • 原型作用域适用于需要动态创建、短生命周期的对象。
  • 需要注意的是,Spring 容器不会完全管理原型作用域的 Bean,销毁和清理需要开发者自行处理。

http://www.ppmy.cn/news/1564751.html

相关文章

Windows蓝牙驱动开发-蓝牙 IOCTL

蓝牙驱动程序堆栈为配置文件驱动程序提供了多个 IOCTL&#xff0c;来收集有关以下内容的信息&#xff1a; 本地蓝牙无线电和系统&#xff1b; 远程蓝牙设备&#xff1b; 会使即插即用 (PnP) 管理器加载配置文件驱动程序的设备&#xff1b; 为收集有关本地蓝牙无线电和系统的…

Ceph与RAID在存储中的协同工作过程

本文将结合架构图&#xff0c;详细讲解Ceph与RAID如何在存储环境中相互配合&#xff0c;共同提供高效且可靠的存储服务。 架构概述 从上图中可以看到&#xff0c;Ceph的架构主要分为四个层次&#xff1a; 客户端和服务接口层&#xff1a;这一层包括客户端访问存储应用的接口…

【深度学习】Pytorch:CUDA 模型训练

在深度学习中&#xff0c;GPU 的强大计算能力能极大地提升模型训练的速度。PyTorch 提供了对 CUDA&#xff08;Compute Unified Device Architecture&#xff09;的原生支持&#xff0c;使得在 GPU 上运行深度学习模型变得简单高效。本文将详细讲解如何使用 PyTorch 在 CUDA 上…

BERT详解

1.背景结构 1.1 基础知识 BERT(Bidirectional Encoder Representations from Transformers)是谷歌提出,作为一个Word2Vec的替代者,其在NLP领域的11个方向大幅刷新了精度,可以说是前几年来自残差网络最优突破性的一项技术了。论文的主要特点以下几点: 使用了双向Transfo…

.NET8.0多线程编码结合异步编码示例

1、创建一个.NET8.0控制台项目来演示多线程的应用 2、快速创建一个线程 3、多次运行程序&#xff0c;可以得到输出结果 这就是多线程的特点 - 当多个线程并行执行时&#xff0c;它们的具体执行顺序是不确定的&#xff0c;除非我们使用同步机制&#xff08;如 lock、信号量等&am…

CTTSHOW-WEB入门-信息搜集11-20

web11 1. 题目&#xff1a; 2. 解题步骤及思路&#xff1a;本题的flag已经给出&#xff0c;主要考点是考察域名的查询&#xff0c;通过查询有时候也可以得到一些有用的信息。 3. 相关知识点&#xff1a;查询域名可以使用nslookup命令使用方法如下&#xff1a;&#xff08;windo…

Type-C充电与智能家居的结合

在科技日新月异的今天&#xff0c;家具已不仅仅是满足基本生活需求的物品&#xff0c;它们正逐渐融入智能化元素&#xff0c;成为提升生活品质的重要一环。其中&#xff0c;家具与USB充电技术的结合&#xff0c;正是这一趋势的生动体现。通过将USB充电端口巧妙地融入家具设计中…

WPS计算机二级•常用图表制作

听说这里是目录哦 绘制饼图&#x1f697;制作动态图表&#x1f68c;制作动态对比图表&#x1f3cd;️目标与实际对比图&#x1f3ce;️基本图表介绍&#x1f69b;线柱图&#x1f69a;能量站&#x1f61a; 绘制饼图&#x1f697; 选中表格数据单元格➡️点击上方菜单栏插入-全部…