当前位置: 首页 > news >正文

从自定义一个作用域开始来了解SpringBean的作用域

你好,这里是codetrend专栏“Spring6全攻略”。

在 Spring 框架中,Bean 的作用域(Scope)定义了 Bean 实例在容器中如何创建、管理和销毁的策略。

Spring 提供了多种 Bean 作用域,每种作用域都有其特定的生命周期和适用场景。

先试试不同的 Bean Scope

下面通过一个简单的 Spring MVC Controller 示例来感受下 Bean 的作用域。

例子代码是这样的:

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.WebApplicationContext;import java.util.UUID;@Configuration
public class AppConfig {@Bean@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)public SingletonBean singletonBean() {return new SingletonBean();}@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public PrototypeBean prototypeBean() {return new PrototypeBean();}@Bean@Scope(WebApplicationContext.SCOPE_SESSION)public SessionBean sessionBean() {return new SessionBean();}
}class SingletonBean {private int count = 0;public void increment() {count++;}public int getCount() {return count;}
}class PrototypeBean {private String id;public PrototypeBean() {this.id = UUID.randomUUID().toString();}public String getId() {return id;}
}class SessionBean {private String id;public SessionBean() {this.id = UUID.randomUUID().toString();}public String getId() {return id;}
}

controller 代码:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ScopeController {@Autowiredprivate SingletonBean singletonBean;@Autowiredprivate ApplicationContext context;@GetMapping("/singleton")public String singletonCount() {singletonBean.increment();return "Singleton Count: " + singletonBean.getCount();}@GetMapping("/prototype")public String prototypeGet() {PrototypeBean prototypeBean = context.getBean(PrototypeBean.class);return "Prototype ID: " + prototypeBean.getId();}@GetMapping("/session")public String sessionGet() {SessionBean prototypeBean = context.getBean(SessionBean.class);return "Session ID: " + prototypeBean.getId();}
}
  • Singleton(单例)的属性持续增加,也就是说访问到的SingletonBean每次都是同一个对象。访问/singleton接口的返回是这样的:
1
2
3
  • Prototype(原型)的属性每次都是不一样的,也就是说明id每次都是调用构造器新创建的。访问/prototype接口的返回是这样的:

Prototype ID: 3ea5af10-ddce-4a89-ad3c-3f07a764f179
Prototype ID: 7e6e9fe8-c0dc-423e-b282-96b7f8087dac
Prototype ID: 7aca1000-484d-46e8-80f7-d444a5a04f49
  • Session(会话)的属性同一窗口是一样的,开启无痕窗口或者其他浏览器就不一样。访问/session接口的返回是这样的:
Prototype ID: 7aca1000-484d-46e8-80f7-d444a5a04f49
Prototype ID: 7aca1000-484d-46e8-80f7-d444a5a04f49
# 开启新的窗口后
Session ID: bd22d310-29e5-4004-8555-9678c08275f0
Session ID: bd22d310-29e5-4004-8555-9678c08275f0

可以直接把样例代码复制到例子里面验证测试。这样我们就对BeanScope作用域有个直观的感受。

自定义一个 Bean Scope

接下来通过实现一个自定义作用域来感受下Bean的作用域原理。

在 Spring 框架中,除了预定义的几种作用域(如 singleton、prototype 等)外,用户还可以自定义作用域以满足特定的业务需求。

自定义作用域允许控制 Bean 的创建、缓存和销毁逻辑,以适应特定的场景,如基于特定条件的实例化策略、自定义生命周期管理等。

自定义步骤:

  • 定义作用域接口:首先,需要实现org.springframework.beans.factory.config.Scope接口,该接口定义了 Bean 作用域的基本行为。
  • 实现逻辑:在自定义的 Scope 接口实现中,需要覆盖getremoveregisterDestructionCallback方法,分别用于获取 Bean 实例、移除 Bean 实例以及注册销毁回调。
  • 注册作用域:在 Spring 配置中注册的自定义作用域,使其可被容器识别和使用。
  • 使用自定义作用域:在 Bean 定义中通过@Scope注解指定使用自定义的作用域名称。

自定义作用域实现

首先自定义作用域实现,也就是实现接口org.springframework.beans.factory.config.Scope

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
import java.util.UUID;public class CustomScope implements Scope {public final static String CUSTOM_SCOPE_NAME = "custom";private final Map<String, Object> scopedObjects = new ConcurrentHashMap<>();private final Map<String, Runnable> destructionCallbacks = new ConcurrentHashMap<>();@Overridepublic Object get(String name, ObjectFactory<?> objectFactory) {Object scopedObject = scopedObjects.get(name);if (scopedObject == null) {scopedObject = objectFactory.getObject();scopedObjects.put(name, scopedObject);}return scopedObject;}@Overridepublic Object remove(String name) {scopedObjects.remove(name);Runnable callback = destructionCallbacks.remove(name);if (callback != null) {callback.run();}return null;}@Overridepublic void registerDestructionCallback(String name, Runnable callback) {destructionCallbacks.put(name, callback);}@Overridepublic Object resolveContextualObject(String key) {// 可以根据需要实现上下文对象解析逻辑return null;}@Overridepublic String getConversationId() {// 返回一个唯一的标识,用于区分作用域上下文return UUID.randomUUID().toString();}
}

可以看到Scope接口其实是对Bean的全生命周期进行管理,包括获取get、缓存和销毁remove和销毁回调等逻辑。这也是作用域的核心原理。

Spring6怎么实现的Scope

这里以org.springframework.web.context.request.RequestScope 为例子来理解Spring6怎么实现BeanScope的。

得益于Spring框架的抽象和封装,这个类的实现代码并没有多少。

  • RequestScope extends AbstractRequestAttributesScope 核心实现在这个类 AbstractRequestAttributesScope

  • get获取对象方法,其中对象的存储放在了ThreadLocal中,也就是RequestContextHolder这个类的核心。

/*** 根据名称获取对象,如果当前请求属性中没有该对象,则使用对象工厂创建一个对象,并将其设置到请求属性中* 然后再次获取该对象,以便进行隐式会话属性更新。作为额外的好处,我们还允许在获取属性级别进行潜在的装饰。* 如果再次获取到的对象不为空(预期情况),则只使用该对象。如果它同时消失了,我们则返回本地创建的实例。*/
public Object get(String name, ObjectFactory<?> objectFactory) {// 获取当前请求的属性RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();// 根据名称和作用域获取对象Object scopedObject = attributes.getAttribute(name, getScope());if (scopedObject == null) {// 使用对象工厂创建对象scopedObject = objectFactory.getObject();// 将创建的对象设置到请求属性中attributes.setAttribute(name, scopedObject, getScope());// 再次获取对象,进行隐式会话属性更新// 并允许进行潜在的装饰Object retrievedObject = attributes.getAttribute(name, getScope());if (retrievedObject!= null) {// 只使用再次获取到的对象(如果仍然存在,这是预期情况)// 如果它同时消失了,我们则返回本地创建的实例scopedObject = retrievedObject;}}// 返回获取到的对象return scopedObject;
}
  • remove 方法也是差不多的。借助工具类RequestContextHolder将缓存在ThreadLocal中的对象移除。
/*** 移除指定名称的对象,如果当前请求属性中存在该对象,则将其从请求属性中移除并返回该对象;否则返回 null*/
public Object remove(String name) {// 获取当前请求的属性RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();// 根据名称和作用域获取对象Object scopedObject = attributes.getAttribute(name, getScope());if (scopedObject!= null) {// 将该对象从请求属性中移除attributes.removeAttribute(name, getScope());// 返回移除的对象return scopedObject;} else {// 返回 nullreturn null;}
}

注册自定义作用域

注册作用域,需要通过BeanFactory的registerScope方法进行注册。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;@Component
public class ScopeBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {beanFactory.registerScope(CustomScope.CUSTOM_SCOPE_NAME, new CustomScope());}
}

验证自定义作用域效果

将Bean注册到Spring容器中,并使用自定义作用域。

public class MyScopeBean {private String id;public MyScopeBean() {this.id = UUID.randomUUID().toString();}public String getId() {return id;}
}import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;@Configuration
public class AppScopeConfig {@Bean@Scope(CustomScope.CUSTOM_SCOPE_NAME)public MyScopeBean myBean() {return new MyScopeBean();}
}

新建一个Controller,访问/customScope接口,返回自定义作用域的Bean实例。

@RestController
public class CustomScopeController {@Autowiredprivate ApplicationContext context;@GetMapping("/customScope")public String customScope() {MyScopeBean prototypeBean = context.getBean(MyScopeBean.class);return "Prototype ID: " + prototypeBean.getId();}
}

访问的结果输出如下:

Session ID: bd22d310-29e5-4004-8555-9678c08275f0
Session ID: bd22d310-29e5-4004-8555-9678c08275f0
Session ID: bd22d310-29e5-4004-8555-9678c08275f0

因为对象全局缓存到了一个MapscopedObjects,所以可以看到这个自定义作用域效果和单例模式基本一致的。

Bean Scope 的分类

Scope描述
singleton(Default) 将单个 bean 定义作用域限定为 Spring IoC 容器中的单个对象实例。
prototype将单个 bean 定义作用域限定为任意数量的对象实例。
request将单个 bean 定义作用域限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有自己的一个基于单个 bean 定义创建的 bean 实例。仅在 Web-aware Spring ApplicationContext 上下文中有效。
session将单个 bean 定义作用域限定为 HTTP Session 的生命周期。仅在 Web-aware Spring ApplicationContext 上下文中有效。
application将单个 bean 定义作用域限定为 ServletContext 的生命周期。仅在 Web-aware Spring ApplicationContext 上下文中有效。
websocket将单个 bean 定义作用域限定为 WebSocket 的生命周期。仅在 Web-aware Spring ApplicationContext 上下文中有效。

其中singletonprototype是比较常用的数据。

Bean Scope 的使用

可以通过在Spring的配置文件(如XML配置文件或Java注解)中指定@Scope注解或<bean>元素的scope属性来定义Bean的Scope。

其中@Scope注解可以是自定义的值或者如下常量:

  • ConfigurableBeanFactory.SCOPE_PROTOTYPE
  • ConfigurableBeanFactory.SCOPE_SINGLETON
  • org.springframework.web.context.WebApplicationContext.SCOPE_REQUEST
  • org.springframework.web.context.WebApplicationContext.SCOPE_SESSION

其中ConfigurableBeanFactory.SCOPE_PROTOTYPE是默认值。

例如:

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;@Component
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class MyPrototypeBean {// Bean内容
}

或者使用XML配置:

<bean id="myBean" class="com.example.MyBean" scope="prototype"><!-- Bean的其他配置 -->
</bean>

选择合适的Bean Scope取决于应用程序的需求。

为什么设计 Bean Scope

Spring 框架设计 Bean 作用域(Scope)的原因主要是为了提供灵活性和资源管理能力,以适应不同应用场景的需求。

不同的 Bean 作用域会影响 Bean 的生命周期、创建方式和在容器中的共享程度,从而影响应用的性能、内存占用和并发处理能力。

以下是 Spring 提供 Bean 作用域设计背后的主要原因:

  • 资源优化:通过作用域设计,Spring 能够根据业务场景高效管理 Bean 的创建与销毁。例如,单例(Singleton)模式可以减少频繁创建实例的开销,原型(Prototype)模式则确保每次请求都得到新的实例,避免了共享状态问题。
  • 并发处理:对于 Web 应用,特定作用域如请求(Request)和会话(Session)使得每个用户请求或会话都有独立的 Bean 实例,解决了并发用户数据隔离的问题,提高了应用的线程安全。
  • 生命周期管理:不同的作用域允许开发者控制 Bean 的生命周期,比如通过自定义作用域实现复杂的生命周期管理逻辑。Spring 容器在 Bean 的创建、初始化、销毁等关键时刻调用生命周期回调方法,增加了灵活性。
  • 可测试性:通过作用域的设计,特别是原型模式,可以更容易地创建独立的测试环境,因为每次测试都能得到全新的实例,减少了测试间状态干扰。
  • 扩展性:Spring 允许开发者自定义作用域,为特定的业务需求或架构设计提供定制化的 Bean 管理方式,增强了框架的扩展性和适应性。
  • 内存管理:合理使用作用域可以减少内存消耗,例如,原型模式避免了单例 Bean 累积大量状态导致的内存泄漏风险,而请求作用域则确保请求结束后自动清理资源。

单例 bean 里面注入了原型 bean

当单例 Bean 中注入原型(Prototype)Bean 时,会出现一个问题:

  • 单例 Bean 在整个应用生命周期中只创建一次。
  • 而原型 Bean 本应每次请求时创建新实例。
  • 但直接注入到单例 Bean 中时,实际上只会注入一次原型 Bean 的实例。
  • 后续对该原型 Bean 的使用都将复用首次注入的同一个实例,这可能并不符合预期。

以下demo可以复现这种情况。

SpringBean的配置:

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;@Configuration
public class FaultAppConfig {@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public PrototypeInjectBean prototypeInjectBean() {return new PrototypeInjectBean();}
}

单例SpringBean:

import java.util.UUID;public class PrototypeInjectBean {private String id;public PrototypeInjectBean() {this.id = UUID.randomUUID().toString();}public String getId() {return id;}
}

测试代码如下:

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class PrototypeFaultController {final private PrototypeInjectBean prototypeInjectBean;protected PrototypeFaultController(PrototypeInjectBean prototypeInjectBean) {this.prototypeInjectBean = prototypeInjectBean;}/*** 原型作用域失效,每次返回同一个id* @return*/@GetMapping("/prototypeDemo1")public String prototypeDemo1() {return "Prototype ID: " + prototypeInjectBean.getId();}}

在不重启应用或者垃圾回收的情况下,访问接口 /prototypeDemo1 原型 Bean 的id值始终是相同的。

Prototype ID: 11893ed8-608c-452b-b2e6-82bc70b5cf97
Prototype ID: 11893ed8-608c-452b-b2e6-82bc70b5cf97
Prototype ID: 11893ed8-608c-452b-b2e6-82bc70b5cf97

那这种常用的使用场景遇到了该怎么解决呢?别急,Spring早已经给出了几种解决办法。

通过完善上面的测试代码给出3中解决方法。

修改完善后的代码如下:


import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public abstract class PrototypeFaultController {@Autowiredprivate ApplicationContext context;@Autowiredprivate ObjectProvider<PrototypeInjectBean> prototypeBeanProvider;final private PrototypeInjectBean prototypeInjectBean;protected PrototypeFaultController(PrototypeInjectBean prototypeInjectBean) {this.prototypeInjectBean = prototypeInjectBean;}/*** 原型作用域失效,每次返回同一个id* @return*/@GetMapping("/prototypeDemo1")public String prototypeDemo1() {return "Prototype ID: " + prototypeInjectBean.getId();}/*** 使用实例工厂方法注入获取原型Bean,每次返回不同id* @return*/@GetMapping("/prototypeDemo2")public String prototypeDemo2() {PrototypeInjectBean prototypeBean = context.getBean(PrototypeInjectBean.class);return "Prototype ID: " + prototypeBean.getId();}/*** Spring 提供了`ObjectProvider`接口(继承自`Provider`接口),它允许延迟查找和实例化 Bean,非常适合在单例 Bean 中按需获取原型 Bean 的新实例。* @return*/@GetMapping("/prototypeDemo4")public String prototypeDemo4() {return "Prototype ID: " + prototypeBeanProvider.getObject().getId();}/*** 使用`@Lookup`注解获取原型Bean,每次返回不同id* @return*/@GetMapping("/prototypeDemo5")public String prototypeDemo5() {return "Prototype ID: " + getPrototypeBean().getId();}@Lookuppublic abstract PrototypeInjectBean getPrototypeBean();}
  • 解决办法1: Spring 提供了ObjectProvider接口(继承自Provider接口),它允许延迟查找和实例化 Bean,非常适合在单例 Bean 中按需获取原型 Bean 的新实例。

通过访问接口/prototypeDemo4可以发现每次返回的id值是不同的。

  • 解决办法2: 可以通过定义一个工厂方法来创建原型 Bean 的实例,然后在单例 Bean 中注入这个工厂方法,每次需要时调用工厂方法获取新实例。

通过访问接口/prototypeDemo2可以发现每次返回的id值是不同的。

  • 解决办法3: 通过@Lookup注解,@Lookup注解是Spring框架中的一个特殊注解,用于在Spring容器中查找另一个Bean,并将其注入到当前Bean中。注意使用@Lookup注解的方法必须是抽象的(abstract)。

通过访问接口/prototypeDemo5可以发现每次返回的id值是不同的。

关于作者

来自一线全栈程序员nine的探索与实践,持续迭代中。

欢迎关注或者点个小红心~

相关文章:

从自定义一个作用域开始来了解SpringBean的作用域

你好&#xff0c;这里是codetrend专栏“Spring6全攻略”。 在 Spring 框架中&#xff0c;Bean 的作用域&#xff08;Scope&#xff09;定义了 Bean 实例在容器中如何创建、管理和销毁的策略。 Spring 提供了多种 Bean 作用域&#xff0c;每种作用域都有其特定的生命周期和适用…...

Android 编译文件简述(Android.mk)

Android 编译文件简述(Android.mk) Android.mk 文件是 Android 构建系统中的一种构建配置文件,使用 GNU Make 语法,用于定义 Android 项目中的模块、库、应用程序、JNI 代码等的编译和链接方式。每个 Android.mk 文件通常对应一个目录,代表构建系统应该如何处理该目录下的源…...

[React] 手动实现CountTo 数字滚动效果

这个CountTo组件npmjs里当然有大把的依赖存在&#xff0c;不过今天我们不需要借助任何三方依赖&#xff0c;造个轮子来手动实现这个组件。 通过研究其他count to插件我们可以发现&#xff0c;数字滚动效果主要依赖于requestAnimationFrame 通过js帧来让数字动起来&#xff0c;…...

9.Admin后台系统

9. Admin后台系统 Admin后台系统也称为网站后台管理系统, 主要对网站的信息进行管理, 如文字, 图片, 影音和其他日常使用的文件的发布, 更新, 删除等操作, 也包括功能信息的统计和管理, 如用户信息, 订单信息和访客信息等. 简单来说, 它是对网站数据库和文件进行快速操作和管…...

redis之集群

一.redis主从模式和redis集群模式的区别 redis主从模式:所有节点上的数据一致&#xff0c;但是key过多会影响性能 redis集群模式:将数据分散到多个redis节点&#xff0c;数据分片存储&#xff0c;提高了redis的吞吐量 二.redis cluster集群的特点 数据分片 多个存储入…...

#9松桑前端后花园周刊-React19beta、TS5.5beta、Node22.1.0、const滥用、jsDelivr、douyin-vue

行业动态 Mozilla 提供 Firefox 的 ARM64 Linux二进制文件 此前一直由发行版开发者或其他第三方提供&#xff0c;目前Mozilla提供了nightly版本&#xff0c;正式版仍需要全面测试后再推出。 发布 React 19 Beta 此测试版用于为 React 19 做准备的库。React团队概述React 19…...

STM32中UART通信的完整C语言代码范例

UART&#xff08;通用异步收发器&#xff09;是STM32微控制器中常用的外设&#xff0c;用于与其他设备进行串行通信。本文将提供一个完整的C语言代码范例&#xff0c;演示如何在STM32中使用UART进行数据传输。 硬件配置 在开始编写代码之前&#xff0c;需要确保以下硬件配置&…...

【ITK统计】第一期 分类器

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享ITK中的分类器及其使用情况,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 在统计分…...

51单片机两个中断及中断嵌套

文章目录 前言一、中断嵌套是什么&#xff1f;二、两个同级别中断2.1 中断运行关系2.2 测试程序 三、两个不同级别中断实现中断嵌套3.1 中断运行关系3.2 测试程序 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 课程需要&#xff1a; 提示&#x…...

VUE 监视数据原理

1、如何监测对象中的数据&#xff1f; 通过setter实现监视&#xff0c;且要在new vue时就传入监测的数据 &#xff08;1&#xff09;对象中后加的属性&#xff0c;vue默认不做响应式处理 &#xff08;2&#xff09;如需给后添加的属性做响应式&#xff0c;请使用如下API&#x…...

Thinkphp使用dd()函数

用过Laravel框架的同学都知道在调试代码的时候使用dd()函数打印变量非常方便&#xff0c;在ThinkPHP6及以上的版本框架中也默认加上了这个函数。但是在ThinkPHP5或更低版本的框架中&#xff0c;dd 并不是一个内置的方法&#xff0c;不过我们可以手动添加这个函数&#xff0c;步…...

Git使用指北

目录 创建一个Git仓库本地仓库添加文件文件提交到本地仓库缓冲区添加远程仓库地址本地仓库推送到远程仓库创建新的分支拉取代码同步删除缓冲区的文件&#xff0c;远程仓库的文件.gitignore文件 创建一个Git仓库 Git仓库分为远程和本地两种&#xff0c;远程仓库如Githu上创建的…...

STM32G030F6P6TR 芯片TSSOP20 MCU单片机微控制器芯片

STM32G030F6P6TR 在物联网&#xff08;IoT&#xff09;设备中的典型应用案例包括但不限于以下几个方面&#xff1a; 1. 环境监测系统&#xff1a; 使用传感器来监测温度、湿度、气压等环境因素&#xff0c;并通过无线通信模块将数据发送到中央服务器或云端平台进行分析和监控。…...

零基础入门学习Python第二阶01生成式(推导式),数据结构

Python语言进阶 重要知识点 生成式&#xff08;推导式&#xff09;的用法 prices {AAPL: 191.88,GOOG: 1186.96,IBM: 149.24,ORCL: 48.44,ACN: 166.89,FB: 208.09,SYMC: 21.29}# 用股票价格大于100元的股票构造一个新的字典prices2 {key: value for key, value in prices.i…...

Java面试题:多线程3

CAS Compare and Swap(比较再交换) 体现了一种乐观锁的思想,在无锁情况下保证线程操作共享数据的原子性. 线程A和线程B对主内存中的变量c同时进行修改 在线程A中存在预期值a,修改后的更新值a1 在线程B中存在预期值b,修改后的更新值b1 当且仅当预期值和主内存中的变量值相等…...

【QEMU系统分析之实例篇(十八)】

系列文章目录 第十八章 QEMU系统仿真的机器创建分析实例 文章目录 系列文章目录第十八章 QEMU系统仿真的机器创建分析实例 前言一、QEMU是什么&#xff1f;二、QEMU系统仿真的机器创建分析实例1.系统仿真的命令行参数2.创建后期后端驱动qemu_create_late_backends()qtest_serv…...

pyside6的调色板QPalette的简单应用

使用调色板需要先导入:from PySide6.QtGui import QPalette 调色板QPalette的源代码&#xff1a; class QPalette(Shiboken.Object):class ColorGroup(enum.Enum):Active : QPalette.ColorGroup ... # 0x0Normal : QPalette.ColorGrou…...

苍穹外卖项目

Day01 收获 补习git Git学习之路-CSDN博客 nginx 作用&#xff1a;反向代理和负载均衡 swagger Swagger 与 Yapi Swagger&#xff1a; 可以自动的帮助开发人员生成接口文档&#xff0c;并对接口进行测试。 项目接口文档网址&#xff1a; http://localhost:8080/doc.html Da…...

error: Execution was interrupted, reason: signal SIGABRT

c json解析时&#xff0c; error: Execution was interrupted, reason: signal SIGABRT const Json::Value points root["shapes"]; if (points.isArray()) { for (unsigned int i 0; i < points.size(); i) { std::cout << " - [" <<…...

HarmaonyOS鸿蒙应用科普课

一、什么是鸿蒙OS&#xff1f; 1.概念&#xff1a; 先给大家讲讲今天讲课的主题&#xff0c;鸿蒙OS是什么&#xff1f;鸿蒙系统大家都知道&#xff0c;就是一个操作系统&#xff0c;我们未来是为的成为鸿蒙程序员。所以我们不要将鸿蒙os完全等同于手机操作系统&#xff0c;太…...

数码管的显示

静态数码管显示 数码管有两种一种的负电压促发,一种是正电压促发,上图是单数码管的引脚 上图是数码管模组的引脚,采用了引脚复用技术 咱们这个单片机由8个单数码管,所以要用上38译码器,如下图 74138使能端,单片机上电直接就默认接通了 74HC245的作用是稳定输入输出,数据缓冲作…...

关于海康相机和镜头参数的记录

对比MV-CS020-10UC和大家用的最多的MV-CS016-10UC 其实前者适合雷达站使用&#xff0c;后者适合自瞄使用 一&#xff1a;MV-CS020-10UC的参数 二&#xff1a;对比 三&#xff1a;海康镜头选型工具...

【JavaScript】运算符

算术运算符 1. 加法运算符&#xff08;&#xff09; 加法运算符用于将两个值相加。如果两个操作数都是数字&#xff0c;则它们将被加在一起。如果其中一个操作数是字符串&#xff0c;则另一个操作数将被转换为字符串&#xff0c;然后执行字符串连接。 运算子不同&#xff0c…...

LabVIEW航空发动机主轴承试验器数据采集与监测

LabVIEW航空发动机主轴承试验器数据采集与监测 随着航空技术的迅速发展&#xff0c;对航空发动机性能的测试与监测提出了更高的要求。传统的数据采集与监测方法已难以满足当前高精度和高可靠性的需求&#xff0c;特别是在主轴承试验方面。基于LabVIEW的航空发动机主轴承试验器…...

CVE-2022-2602:unix_gc 错误释放 io_uring 注册的文件从而导致的 file UAF

前言 复现该漏洞只是为了学习相关知识&#xff0c;在这里仅仅做简单记录下 exp&#xff0c;关于漏洞的详细内容请参考其他文章&#xff0c;最后在 v5.18.19 内核版本上复现成功&#xff0c;v6.0.2 复现失败 漏洞利用 diff --git a/include/linux/skbuff.h b/include/linux/s…...

LSTM实战笔记(部署到C++上)——更新中

前几天由于自己的个人原因停止了学习 接下里继续更新一些自己项目中所用到的神经网络等 ——————————————————————————————————————————— LSTM代码介绍 建立LSTM模型时需要设置一些参数&#xff0c;包括输入数据的形状、LSTM层的…...

鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据

基本概念 队列又称消息队列&#xff0c;是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息&#xff0c;并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息&#xff0c;当队列中的消息为空时&#xff0c;挂起读取任务…...

Sentinel流量防卫兵

1、分布式服务遇到的问题 服务可用性问题 服务可用性场景 服务雪崩效应 因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程&#xff0c;就叫服务雪崩效应导致服务不可用的原因&#xff1a; 在服务提供者不可用的时候&#xff0c;会出现大量重试的情况&…...

微信小程序:14.什么是wxs,wxs的使用

wxs是小程序独有的一套脚本语言&#xff0c;结合wxml&#xff0c;可以构建出页面的结构 wxs的应用场景 wxml中无法调用在页面的js中定义的函数&#xff0c;但是wxml可以调用wxs中定义的函数。因此小程序中wxs的典型应用场景就是过滤器 wxs和js的关系 wxs有自己的数据类型 …...

Django运行不提示网址问题

问题描述&#xff1a;运行django项目不提示网址信息&#xff0c;也就是web没有起来&#xff0c;无法访问。 (my-venv-3.8) PS D:\Project\MyGitCode\public\it_blog\blog> python .\manage.py runserver INFO autoreload 636 Watching for file changes with StatReloader …...

外贸做哪个网站平台/故事型软文广告

原标题&#xff1a;Pythonrequestsunittestexcel实现接口自动化测试框架 一、框架结构&#xff1a;工程目录二、Case文件设计三、基础包 base 3.1 封装get/post请求&#xff08;runmethon.py&#xff09; 1importrequests 2importjson 3classRunMethod: 4defpost_main(self,url…...

企业只有建立自己的网站/百度竞价排名是什么

stm32f4xx_conf.h文件的讲解 在我的上一篇博客中又讲解到stm32f4xx.h文件的讲解&#xff0c;在那个头文件中包含了4个头文件。 这四个头文件中第一个是非常难的&#xff0c;如果你32学的不是很扎实的话劝你们最好别去碰&#xff0c;涉及很多汇编和底层知识你只需要知道每次你…...

网站建设有利点/广告联盟接单赚钱平台

excel另存为PDF&#xff0c;然后保持缩放...

南阳企业网站制作/深圳刚刚突然宣布

1、什么是五大学科竞赛 五大学科竞赛分别是数学、物理、化学、生物和信息学&#xff0c;竞赛分为市级、省级、国决和世界奥赛四个级别&#xff0c;竞赛生需要通过层层选拔才能最终站在世界舞台上。 2、参加五大学科竞赛的时间 黄金时期&#xff1a;高一高二&#xff08;尤其是…...

深圳制作网站建设推广/沈阳seo排名优化推广

WIN2003 IIS最小权限分配.bat代码如下:echo off echo "虚拟主机C盘权限设定" echo "Author:an85.com" echo "删除C盘的everyone的权限" cd/ cacls "%SystemDrive%" /r "everyone" /e cacls "%SystemRoot%" /r &qu…...

南京百度做网站电话/百度一下电脑版首页网址

GC管理的主要区域是Java堆&#xff0c;一般情况下只针对堆进行垃圾回收。方法区、JVM栈和Native栈不被GC所管理&#xff0c;因而选择这些非堆区的对象作为GC roots&#xff0c;被GC roots引用的对象不被GC回收。 一个对象可以属于多个root&#xff0c;GC root有几下种&#xff…...