@Scope(“prototype“)

ops/2025/1/19 18:17:19/

@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/ops/151447.html

相关文章

opencv笔记1

openCV是什么&#xff1f; 它的全称是Open source Computer Vision Library,开放源代码计算机视觉库。 后面亚博小车有颜色识别并追踪、人脸识别并追踪实践项目。先了解下基础函数使用。 一 图像的读取与展示 1图像的读取 img cv2.imread(yahboom.jpg, 0) 第一个参数是…

SQL刷题快速入门(三)

其他章节&#xff1a; SQL刷题快速入门&#xff08;一&#xff09; SQL刷题快速入门&#xff08;二&#xff09; 承接前两个章节&#xff0c;本系列第三章节主要讲SQL中where和having的作用和区别、 GROUP BY和ORDER BY作用和区别、表与表之间的连接操作&#xff08;重点&…

在 macOS 上,用命令行连接 MySQL(/usr/local/mysql/bin/mysql -u root -p)

根据你提供的文件内容&#xff0c;MySQL 的安装路径是 /usr/local/mysql。要直接使用 mysql 命令&#xff0c;你需要找到 mysql 可执行文件的路径。 在 macOS 上&#xff0c;mysql 客户端通常位于 MySQL 安装目录的 bin 子目录中。因此&#xff0c;完整的路径应该是&#xff1…

码云gitee 新建仓库 添加公钥

码云gitee 新建仓库 添加公钥 文章目录 码云gitee 新建仓库 添加公钥新建仓库生成公钥管理个人公钥安全验证 码云这个网站是一个代码托管平台&#xff0c;在国内可以无限制的使用&#xff0c;在这个网站上&#xff0c;也可以搜索到一些github上面的内容。进入这个网站&#xff…

Kubernetes集群架构-垃圾回收

Kubernetes集群架构-垃圾回收 Kubernetes 集群架构 - 垃圾回收属主与依赖级联删除前台级联删除后台级联删除被遗弃的依赖对象 未使用容器和镜像的垃圾回收容器镜像生命周期未使用容器镜像的垃圾收集容器垃圾收集 配置垃圾收集 链接 Kubernetes 集群架构 - 垃圾回收 垃圾回收是…

浅谈计算机网络04 | 现代网络需求与技术支撑

现代网络需求与技术支撑 一、网络和因特网流量的类型剖析1.1 弹性流量的自适应特征1.2 非弹性流量的刚性特征1.3 实时流量特性 二、特定领域的网络需求解析2.1 大数据环境下的网络需求分析2.2 云计算环境下的网络需求分析2.3 移动数据环境下的网络需求分析 三、QoS和QoE&#x…

支付宝“政府补贴”bug事件背后的权限管理启示

1月16日&#xff0c;支付宝发生了一起备受关注的“政府补贴”bug事件。在当天14:40-14:45期间&#xff0c;多位用户在使用支付宝进行购物、个人转账、购票、还信用卡等操作时&#xff0c;被提示“政府补贴”&#xff0c;享受到了20%的优惠。这一事件迅速登上微博热搜&#xff0…

Ubuntu -- 几行命令使用Ollama部署本地AI大模型, 仅调用api, 快速测试api效果

需求 需要在本地快速部署一个大模型, 然后使用 局域网 的其他电脑进行 api调用为了快速测试, 大模型选择了 qwen2:0.5B 进行快速测试 开始 下载安装 ollama curl -fsSL https://ollama.com/install.sh | sh验证安装 ollama --version下载安装模型并运行 ollama run qwen2:…