Spring学习笔记_18——@Scope

@Scope

1. 说明

@Scope注解是Spring中提供的一个能够指定Bean的作用范围的注解,通过@Scope注解可以指定创建的Bean是单例的,还是原型的,也可以使用@Scope注解指定Bean在Web中的作用域,还可以自定义作用域。

2. 场景

  1. 非单例Bean
  • 默认情况下,Spring容器中的bean是单例的(singleton),这意味着在整个应用程序的生命周期中,Spring容器只会为该bean创建一个实例。如果你需要每次请求一个新的bean实例(例如,对于有状态的服务),你可以使用@Scope("prototype")来指定bean的作用域。
  1. Web作用域
  • 在Web应用程序中,你可能会希望bean的作用域与HTTP请求或会话相关联。
    • 使用@Scope("request"):每次HTTP请求都会创建一个新的bean实例,并且该实例仅在当前请求内有效。
    • 使用@Scope("session"):每次HTTP会话都会创建一个新的bean实例,并且该实例在当前会话内有效。这对于需要在用户会话期间保持状态的bean非常有用。
  • 注意:要使用这些作用域,你需要确保Spring的Web应用上下文(例如,XmlWebApplicationContextAnnotationConfigWebApplicationContext)已正确配置。
  1. 自定义作用域
  • 如果你需要一种Spring未提供的作用域(例如,基于每个线程或每个自定义上下文的bean实例),你可以通过实现org.springframework.beans.factory.config.Scope接口来创建自定义作用域,并使用@Scope注解的value属性或scopedProxy属性来引用它。
  1. 代理作用域Bean(使用scopedProxy):
  • 当你在单例bean中注入作用域为requestsession或自定义作用域的bean时,由于单例bean的生命周期与作用域bean的生命周期不匹配,直接注入可能会导致问题。为了解决这个问题,你可以使用scopedProxy属性来创建一个代理对象,该代理对象会在需要时延迟获取作用域bean的实例。
  • 例如:@Scope(value = "request", scopedProxy = ScopedProxyMode.TARGET_CLASS)
  1. 在配置类中定义Bean时
  • 当你使用Java配置(@Configuration类)来定义bean时,你可以使用@Scope注解来指定bean的作用域。这通常与@Bean注解一起使用。
  1. 在组件类上
  • 你也可以在用@Component@Service@Repository注解标记的类上使用@Scope注解来指定这些组件的作用域。

3. 源码

/*** @author Mark Fisher* @author Chris Beams* @author Sam Brannen* @since 2.5* @see org.springframework.stereotype.Component* @see org.springframework.context.annotation.Bean*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {// value:表示作用范围,可以取如下值。// singleton:表示单例Bean,IOC容器在启动时,就会创建Bean对象。如果标注了@Lazy注解,IOC容器在启动时,就不会创建Bean对象,会在第一次从IOC容器中获取Bean对象时,创建Bean对象。后续每次从IOC容器中获取的都是同一个Bean对象,同时,IOC容器会接管单例Bean对象的生命周期。// prototype:表示原型Bean。IOC容器在启动时,不会创建Bean对象,每次从IOC容器中获取Bean对象时,都会创建一个新的Bean对象。并且@Lazy注解对原型Bean不起作用,同时,IOC容器不会接管原型Bean对象的生命周期// request:表示作用域是当前请求范围。// session:表示作用域是当前会话范围。// application:表示作用域是当前应用范围。@AliasFor("scopeName")String value() default "";/*** @since 4.2*/// Spring4.2版本开始新增的属性,作用与value属性相同@AliasFor("value")String scopeName() default "";// 指定Bean对象使用的代理方式,可以取如下值。// DEFAULT:默认值,作用与NO相同。// NO:不使用代理。// INTERFACES:使用JDK基于接口的代理。// TARGET_CLASS:使用CGLIB基于目标类的子类创建代理对象。ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

4. Demo

4.1 单例
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;@Component
@Scope("singleton")
public class SingletonBean {public SingletonBean() {System.out.println("SingletonBean created: " + this);}
}
4.2 原型

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

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;@Component
@Scope("prototype")
public class PrototypeBean {public PrototypeBean() {System.out.println("PrototypeBean created: " + this);}
}
4.3 请求

每个HTTP请求都有自己的Bean实例

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {public RequestScopedBean() {System.out.println("RequestScopedBean created: " + this);}
}
4.4 会话

同一个HTTP Session 共享一个Bean实例

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionScopedBean {public SessionScopedBean() {System.out.println("SessionScopedBean created: " + this);}
}
4.5 应用

整个Web应用程序范围内只有一个实例

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;@Component
@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ApplicationScopedBean {public ApplicationScopedBean() {System.out.println("ApplicationScopedBean created: " + this);}
}
4.6 WebSocket

每个WebSocket链接都有自己的Bean实例

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;
import org.springframework.web.socket.config.annotation.WebSocketScope;@Component
@Scope(value = WebSocketScope.class, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class WebSocketScopedBean {public WebSocketScopedBean() {System.out.println("WebSocketScopedBean created: " + this);}
}
4.7 自定义作用域

首先,定义一个自定义作用域

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> scopeMap = new HashMap<>();@Overridepublic Object get(String name, ObjectFactory<?> objectFactory) {return scopeMap.computeIfAbsent(name, k -> objectFactory.getObject());}@Overridepublic Object remove(String name) {return scopeMap.remove(name);}// 其他方法可以根据需求进行实现@Overridepublic void registerDestructionCallback(String name, Runnable callback) {}@Overridepublic Object resolveContextualObject(String key) {return null;}@Overridepublic String getConversationId() {return "custom-scope";}
}

在配置类中注册这个自定义作用域

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic static CustomScope customScope() {return new CustomScope();}@Beanpublic static CustomScopeConfigurer customScopeConfigurer(CustomScope customScope) {CustomScopeConfigurer configurer = new CustomScopeConfigurer();configurer.addScope("custom", customScope);return configurer;}
}

使用自定义作用域的Bean

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;@Component
@Scope("custom")
public class CustomScopedBean {public CustomScopedBean() {System.out.println("CustomScopedBean created: " + this);}
}

以下是一些可能需要自定义作用域的业务场景:

  1. 基于特定条件的实例化策略
  • 当Bean的创建需要基于某些特定的业务条件或逻辑时,可以使用自定义作用域来控制Bean的实例化过程。例如,可能需要根据用户的角色或权限来创建不同配置的Bean实例。
  1. 自定义生命周期管理
  • 对于某些特殊的Bean,可能需要实现自定义的生命周期管理逻辑,包括创建、缓存、使用和销毁等。自定义作用域允许开发者完全控制这些过程,以适应特定的业务需求。
  1. 非标准的请求作用域
  • 在某些情况下,可能需要在非标准的请求范围内共享Bean实例。例如,在批处理应用程序中,可能需要为每个批处理任务创建一个独立的Bean实例,而这些任务并不是由HTTP请求触发的。此时,可以通过自定义作用域来实现这种需求。
  1. 跨多个HTTP请求或会话的状态管理
  • 在某些Web应用程序中,可能需要跨多个HTTP请求或会话来维护某些状态信息。虽然Session作用域可以在单个会话内共享状态,但如果需要在多个会话之间共享状态,或者需要更复杂的状态管理逻辑,那么自定义作用域可能是一个更好的选择。
  1. 与第三方系统集成
  • 当Spring应用程序需要与第三方系统集成时,可能需要遵循特定的生命周期管理规则或协议。例如,某些第三方库可能要求在每个请求开始时创建一个新的实例,并在请求结束时销毁该实例。此时,可以通过自定义作用域来确保与这些系统的兼容性和集成性。
  1. 测试与模拟
  • 在进行单元测试或集成测试时,可能需要模拟不同的作用域行为来验证应用程序的正确性。自定义作用域提供了一种灵活的方式来模拟这些行为,并帮助开发者发现潜在的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/2417.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

游游的游戏大礼包

游游的游戏大礼包 import java.util.*; public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);long n in.nextInt();long m in.nextInt();long a in.nextInt();long b in.nextInt();long ret 0;for(long x 0; x < Math.…

详解ARM汇编条件标志

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 条件标志 在 ARM 指令集中&#xff0c;条件标志是控制指令执行的一种机制&#xff0c;它们用于实现条件分支、比较和其他逻辑操作。 我们平时使用 IDA 调试程…

Navicat Premium安装卸载及使用教程教程

Navicat Premium 17 安装卸载及使用教程教程 0. 卸载 没安装过 Navicat 直接跳过本步骤即可。 正常卸载顺序即可&#xff0c;网上很多教程&#xff0c;这里不演示了 如果怕卸载不干净&#xff0c;最后时候可以执行一下压缩包里面的无限试用 Navicat.bat 即可成功删除Navicat…

Backbone网络详解

Backbone 网络&#xff08;主干网络&#xff09;是深度学习模型中的一个重要组成部分&#xff0c;尤其在计算机视觉任务中。Backbone 网络的主要作用是从输入数据中提取有用的特征&#xff0c;为后续的任务&#xff08;如分类、检测、分割等&#xff09;提供强大的特征表示。常…

Jenkins找不到maven构建项目

有的可能没有出现maven这个选项 解决办法&#xff1a;需要安装Maven项目插件 输入​Maven Integration plugin​

【339】基于springboot的新能源充电系统

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;新能源充电系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解…

Godot Zelda教程练习1

提示&#xff1a;B站链接&#xff1a;Godot Zelda教程练习 资产链接&#xff1a;项目资产 Godot版本&#xff1a;4.3 文章目录 一、新建项目1、创建项目2、设置项目标签3、项目基本设置4、导入资产 二、图块集和自动平铺1、创建TileMapLayer2、创建Terrian Set1、Match Siders(…

【案例】旗帜飘动

开发平台&#xff1a;Unity 6.0 开发工具&#xff1a;Shader Graph 参考视频&#xff1a;Unity Shader Graph 旗帜飘动特效   一、效果图 二、Shader Graph 路线图 三、案例分析 核心思路&#xff1a;顶点偏移计算 与 顶点偏移忽略 3.1 纹理偏移 视觉上让旗帜保持动态飘动&a…

Android亮屏Job的功耗优化方案

摘要: Job运行时会带来持锁的现象,目前灭屏放电Job的锁托管已经有doze和绿盟标准监管,但是亮屏时仍旧存在过长的持锁现象,故为了优化功耗和不影响用户体验下,新增亮屏放电下如果满足冻结和已运行过一次Job,则进行job限制,当非冻结时恢复的策略 1.现象: (gms_schedu…

Java面试经典 150 题.P55. 跳跃游戏(009)

本题来自&#xff1a;力扣-面试经典 150 题 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台https://leetcode.cn/studyplan/top-interview-150/ 题解&#xff1a; class Solution {public boolean canJump(int[] nums) {int…

源码解析篇 | YOLO11:计算机视觉领域的新突破 !对比YOLOv8如何 ?

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。在2024年9月27日盛大举行的YOLO Vision 2024活动上&#xff0c;Ultralytics公司震撼发布了YOLO系列的最新成员—YOLO11。作为Ultralytics YOLO系列实时目标检测器的最新迭代&#xff0c;YOLO11凭借尖端的准确性、速度和效率…

mac m1 docker本地部署canal 监听mysql的binglog日志

mac m1 docker本地部署canal监听mysql的binglog日志(虚拟机同理) 根据黑马视频部署 1.docker 部署mysql 1.docker拉取mysql 镜像 因为m1是arm架构.需要多加一条信息 正常拉取 docker pull mysql:tagm1拉取 5.7的版本. tag需要自己指定版本 docker pull --platform linux/x…

复现LLM:带你从零训练tokenizer

1. 引言 分词器是每个大语言模型必不可少的组件&#xff0c;但每个大语言模型的分词器几乎都不相同。如果要训练自己的分词器&#xff0c;可以使用huggingface的tokenizers框架&#xff0c;tokenizers包含以下主要组件&#xff1a; Tokenizer: 分词器的核心组件&#xff0c;定…

Nginx防盗链配置

1. 什么是盗链? 盗链是指服务提供商自己不提供服务的内容&#xff0c;通过技术手段绕过其它有利益的最终用户界面&#xff08;如广告&#xff09;&#xff0c;直接在自己的网站上向最终用户提供其它服务提供商的服务内容&#xff0c;骗取最终用户的浏览和点击率。受益者不提供…

DAY53|| 42. 接雨水|84.柱状图中最大的矩形

42. 接雨水(超经典款&#xff09; 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2…

字节跳动(抖音)软件测试月薪23K岗、技术二面面试题最新出炉

测试人员在测试中的任务是什么&#xff1f; ① 尽可能早地找出系统中的bug&#xff1b; ② 避免软件开发过程中缺陷的出现&#xff1b; ③ 协助开发定位bug.以及后续bug跟踪 ④ 一切以用户的需求为标准&#xff0c;确保软件的质量 HTTP与HTTPS协议的区别&#xff1f; …

新160个crackme - 091-DOSKEY-CRACKME2

运行分析 需破解Name和Password PE分析 upx壳&#xff0c;32位 手动脱壳 x32dbg打开程序&#xff0c;按一下F8&#xff0c;根据ESP定律&#xff0c;在此处下断点按一下F9&#xff0c;两下F8&#xff0c;来到OEP处00401000打开Scylla&#xff0c;点击转储保存文件点击IAT自动搜索…

Python(包和模块)

包 定义 包是将模块以文件夹的组织形式进行分组管理的方法&#xff0c;以便更好地组织和管理相关模块。 包是一个包含一个特殊的__init__.py文件的目录&#xff0c;这个文件可以为空&#xff0c;但必须存在&#xff0c;以标识目录为Python包。 包可以包含子包&#xff08;子…

ClickHouse安装

一&#xff0c;ClickHouse介绍 ClickHouse 是一个开源的列式数据库管理系统&#xff08;Column-Oriented DBMS&#xff09;&#xff0c;由俄罗斯的 Yandex 公司开发。它最初是为 Yandex 的 Metrica 分析服务设计的&#xff0c;用于处理大规模的数据分析任务。ClickHouse 能够提…

网络设置:静态IP与动态IP,何去何从?

在配置网络设备时&#xff0c;一个基础而重要的选择便是决定使用静态IP地址还是动态IP地址。这一决策直接影响到网络的连接性、管理便捷性以及安全性。静态IP与动态IP各有其独特的优势与适用场景&#xff0c;选择何种方式&#xff0c;需根据实际需求与网络环境来权衡。本文旨在…