Spring源码分析之BeanFactory接口的解析

news2024/12/18 17:23:31

前言:

   在我们的前两篇文章当中我们看完之后其实我们都会发现当我们进行相关的重要的行为的时候如我们看到的GetBean或者在Register方法的时候会出现BeanFactroy进行调用那么这个时候我们就会产生一个疑惑这个到底是什么为什么这么重要,在我没有说的时候我们从字面上进行一个简单的分析就是说这个是一个Bean工厂那么工厂不就是用来进行加工的那么加工肯定是需要原料以及加工流程的这么想的话其实已经把这个功能基本上都全部进行概括了,那么下面的话我们就来进行解说。

1.用到BeanFactory的地方:这里的话就大概进行记录

//这个就是对多播器的Bean进行一次的注册
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);

2.什么是BeanFactory:

  BeanFactory他就是一个顶级的工厂的接口,那么就是生产以及管理Bean的一个工厂,那么这个接口也是SpringIOC容器的一个核心接口提供了一些通用的方法如:getBean,containsBean方法但是这个只是一个接口那么就是他的实现类如:如 DefaultListableBeanFactoryXmlBeanFactoryApplicationContext等下面的话就来看看这个接口的源码:

public interface BeanFactory {
	//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
	//如果需要得到工厂本身,需要转义
	String FACTORY_BEAN_PREFIX = "&";

	//根据bean的名字,获取在IOC容器中得到bean实例
	Object getBean(String name) throws BeansException;

	//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
	<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	//提供对bean的检索,看看是否在IOC容器有这个名字的bean
	boolean containsBean(String name);

	//根据bean名字得到bean实例
    //这个Bean是不是单例
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    //是不是多例的
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
     //用于检查给定名称的 Bean 是否可以被赋值给指定的目标类型。
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
	//得到bean实例的Class类型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
	String[] getAliases(String name);
}

3.BeanFactory接口的大家族

(这个就是以DefaultListableBeanFactory这个是Spring默认的工厂实现为例):其实这个就是一种继承的关系也就是可以在实现父类的功能的基础之上可以实现一些自己的额外的一些功能

1.ListableBeanFactory:

   这个接口有几大说明的点 第一点就是说实现这个接口的工厂可以一次性批量获得其管理的Bean而不是一个个进行获得 第二点为只会管理当前工厂里面的Bean而不是管其他工厂的Bean,如果说你必须要管的话那么就是可以通过BeanFactoryUtils工具类才能实现 第三点就是说这个里面的方法是对工厂里面的BeanDefinition起作用

public interface ListableBeanFactory extends BeanFactory {
	
    // 对BeanDefinition的一些细节操作
	boolean containsBeanDefinition(String beanName);
	int getBeanDefinitionCount();
    String[] getBeanDefinitionNames();
    
    // 对 BeanFactory 中获取ObjectProvider方法的拓展
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType, boolean allowEagerInit);
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType, boolean allowEagerInit);
    
    // 获取指定类型(子类)的bean names
    // boolean includeNonSingletons 参数决定是否考虑 singleotn 以外的bean
    // boolean allowEagerInit 是否初始化对应FactoryBean,如果false则类型直接匹配对应的FactoryBean
    String[] getBeanNamesForType(ResolvableType type);
    String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
    String[] getBeanNamesForType(@Nullable Class<?> type);
    String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
    
    /**
    	基本同上,返回的 Map 结构
    	k:beanName
    	v:beanInstance
    **/
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
	<T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException;

    // 返回指定注解的beanName数组
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
    
    // 返回指定注解的bean实例集合:beanName -> bean 实例
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
    
    // 获取指定 beanName 上的注解
    // 同样涉及 FactoryBean 初始化的问题,由参数 allowFactoryBeanInit 决定
    @Nullable
	<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
			throws NoSuchBeanDefinitionException;
    @Nullable
	<A extends Annotation> A findAnnotationOnBean(
			String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
			throws NoSuchBeanDefinitionException;
    <A extends Annotation> Set<A> findAllAnnotationsOnBean(
			String beanName, Class<A> annotationType, boolean allowFactoryBeanInit)
			throws NoSuchBeanDefinitionException;
}    

2.HierarchicalBeanFactory:

  这个接口的实现就是比较简单了就是实现了分层的能力如不同的模块可以拥有不同BeanFactory但是可以共享一些全局配置的一些属性,可以访问父工厂里面的Bean

3.AutowireCapableBeanFactory:

  这个接口的话 第一点实现一个自动装配的能力,第二点还提供了控制Spring中Bean对象的生命周期的一整套的方法为 实例化 属性填充 初始化回调(这个里面就是会设置到后置处理器的回调的处理)这个过程 第三点:允许非 Spring 组件的实例也借助它来实现自动装配以及控制Bean的生命周期

public interface AutowireCapableBeanFactory extends BeanFactory {

	//这个就是表示的就是进行不进行依赖注入
	int AUTOWIRE_NO = 0;

	//这个就是表示通过name进行依赖注入
	int AUTOWIRE_BY_NAME = 1;
	//这个就是表示的就是通过type进行依赖注入
	int AUTOWIRE_BY_TYPE = 2;

	//这个就是表示的就是构造方法的依赖注入
	int AUTOWIRE_CONSTRUCTOR = 3;

	//这个是根据类的结构选择合适的依赖注入的方式但是这个已经过时了
	@Deprecated
	int AUTOWIRE_AUTODETECT = 4;
	//这个就是说根据这个的后缀进行依赖注入
	String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
	//这个就是说创建一个新的Bean的实例
	<T> T createBean(Class<T> beanClass) throws BeansException;
	//对于给定的Bean对象进行属性填充
	// 通过after-instantiation 和 property post-processing 回调的执行
	void autowireBean(Object existingBean) throws BeansException;

	//这个就是通过自动装配的话然后配置这个Bean对象
	// 如设置这个Bean的名字以及BeanFactory也可以是后置处理器
	Object configureBean(Object existingBean, String beanName) throws BeansException;

	//-------------------------------------------------------------------------
	// 下面的话就是可以控制一个Bean的生命周期的全过程:
	    //1.进行是实例化的处理
	    //2.进行属性填充
	   //3.初始化
	//-------------------------------------------------------------------------
	/*这个就是对Bean进行实例化
	*1.通过这个Bean的Class对象进行创建(这个毫无疑问就是进行反射)
	*2.自动装配的模式是byType还是说是byName
	*3.应用所有的BeanPostProcessor回调(这个就是进行后置处理器)
	* */
	@Deprecated(since = "6.1")
	Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;see #applyBeanPostProcessorsAfterInitialization
	 */
	//这个就是通过自动装配的策略创建一个实例但是不应用标准的后置处理器
	Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
	//这个就是对Bean对象进行属性填充一些已经存在的Bean对象通过name或者说是type
	void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
			throws BeansException;

	//通过BeanName对已经创建成功的Bean进行属性赋值
	void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;

	//这个就是引用后置处理器也就是说在Bean初始化之前进行一些操作
	@Deprecated(since = "6.1")
	Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException;
	//这个就是进行初始化Bean
	//这个就是要应用一些工厂的回调如setBeanName setFactory
	//除此以外还会应用所有的BeanPostProcessor
	Object initializeBean(Object existingBean, String beanName) throws BeansException;

	//这个就是说应用这个方法的话就是Bean初始话之后就会进行一些额外逻辑的处理
	@Deprecated(since = "6.1")
	Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException;
     //这个就是要销毁Bean
	 // 使用DisposableBean接口定义的销毁方法
	void destroyBean(Object existingBean);
    //匹配属性对应的Bean
	//解析唯一匹配给定对象类型(如果有的话)的bean实例,包括它的bean名称
	//如果我们通过调用GetBean()方法匹配多个的Bean的话那么其实就是
	//getBean(class)的变体
	<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
	//解析给定bean名称的bean实例, 向目标工厂方法公开提供依赖描述符。
	// 这实际上是getBean(String, Class)的一个变体,
	Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;

	@Nullable
	 // 针对此工厂中定义的bean解析指定的依赖项,注入的时候很有用。
	 // 通过一个依赖的描述(对方法,字段,构造器的抽象),获得一个bean
	Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;

	//它负责根据给定的依赖描述符在Bean工厂中查找并返回一个匹配的Bean实例
	@Nullable
	Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;

}

4.ConfigurableBeanFactory

  这个接口的话其实就是继承了HierarchicalBeanFactory接口那么在基本的分层功能的基础上拓展了一些配置功能

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
	//作用域是单例的
	String SCOPE_SINGLETON = "singleton";
	//作用域是多例的
	String SCOPE_PROTOTYPE = "prototype";
	//设置父BeanFactory
	void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
	//设置Bean的类加载器默认的情况下就是线程上下文类加载器
	void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);
	@Nullable
	//获得类加载器
	ClassLoader getBeanClassLoader();
	//设置临时的类加载器为了类型的匹配默认是没有的
	void setTempClassLoader(@Nullable ClassLoader tempClassLoader);
	@Nullable
	//获得临时的类加载器
	ClassLoader getTempClassLoader();
	//设置Bean的元数据的缓存
	// 如果关闭这个设置的话那么创建一个Bean实例的话将重新查询classloader
	//则这个就是体现出缓存的作用就是提高效率
	void setCacheBeanMetadata(boolean cacheBeanMetadata);
	boolean isCacheBeanMetadata();
	// 设置和获取SpEL表达式解析器
	void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver);
	@Nullable
	BeanExpressionResolver getBeanExpressionResolver();
	//设置以及获得后台的引导的任务执行器
	void setBootstrapExecutor(@Nullable Executor executor);
	@Nullable
	Executor getBootstrapExecutor();
	//设置以及获得转换服务
	void setConversionService(@Nullable ConversionService conversionService);
	@Nullable
	ConversionService getConversionService();
	//添加属性编辑器
	void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);
	void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);
	void copyRegisteredEditorsTo(PropertyEditorRegistry registry);
	//配置和获取类型转化器,
	// 相当于整合了 ConversationService 和 PropertyEditorRegister
	void setTypeConverter(TypeConverter typeConverter);
	TypeConverter getTypeConverter();
	//为注入的值添加一个String解析器
	void addEmbeddedValueResolver(StringValueResolver valueResolver);
	boolean hasEmbeddedValueResolver();
	@Nullable
	String resolveEmbeddedValue(String value);
	//添加以及获取Bean的后置处理器
	void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
	int getBeanPostProcessorCount();
	//注册自定义的作用范围
	void registerScope(String scopeName, Scope scope);
	String[] getRegisteredScopeNames();
	@Nullable
	Scope getRegisteredScope(String scopeName);
	//设置以及获得启动的步骤
	void setApplicationStartup(ApplicationStartup applicationStartup);
	ApplicationStartup getApplicationStartup();
	//从被给的BeanFactory拷贝一些配置
	void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);
	//注册以及解决别名
	void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;
	void resolveAliases(StringValueResolver valueResolver);
	//获得合并的Bean定义
	BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	//是否为工厂Bean
	boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;
	//设置Bean的创建的状态
	void setCurrentlyInCreation(String beanName, boolean inCreation);
	//判断Bean是否在创建中
	boolean isCurrentlyInCreation(String beanName);
	//注册一个依赖的Bean在这个Bean在被销毁之前
	void registerDependentBean(String beanName, String dependentBeanName);
	//如果有的话,返回指定bean的所有bean的名称
	String[] getDependentBeans(String beanName);
	//如果有的话,返回指定bean的依赖的所有bean的名称
	String[] getDependenciesForBean(String beanName);

	//销毁给定的Bean的名字的Bean
	void destroyBean(String beanName, Object beanInstance);
	//销毁指定作用域的Bean
	void destroyScopedBean(String beanName);
	//销毁这个工厂里面的所有的单例的Bean包括实现disposable接口的Bean
	void destroySingletons();
}

5.ConfigurableListableBeanFactory:

  这个接口的话就是整合上面所有的BeanFactory接口的全部的方法除此以外还额外拓展了preInstantiateSingletons方法

preInstantiateSingletons(): 

  这个方法就是对Bean进行一些提前的实例化确保所有被配置为单例且不是懒加载的Bean都被提前创建和初始化(会走完整个Bean的生命周期)提高整体的一个效率如:数据库管理池,缓存管理器这些Bean

	public void preInstantiateSingletons() throws BeansException {
		// 记录日志,跟踪预实例化单例的过程
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		// 创建一个当前 Bean 定义名称列表的副本,以允许在初始化方法中注册新的 Bean 定义
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
		// 触发所有非懒加载的单例 Bean 的初始化
		List<CompletableFuture<?>> futures = new ArrayList<>();
		// 设置标志,表示当前处于预实例化阶段
		this.preInstantiationPhase = true;
		this.preInstantiationThread.set(PreInstantiation.MAIN);
		try {
			// 遍历所有 Bean 名称
			for (String beanName : beanNames) {
				// 获取合并后的本地 Bean 定义
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 如果 Bean 不是抽象的且是单例的
				if (!mbd.isAbstract() && mbd.isSingleton()) {
					// 预实例化单例 Bean,并将返回的 CompletableFuture 添加到 futures 列表中
					//因为有的Bean是可以进行提前的创建的提高效率
					//进行Bean的创建
					CompletableFuture<?> future = preInstantiateSingleton(beanName, mbd);
					if (future != null) {
						futures.add(future);
					}
				}
			}
		} finally {
			// 清除预实例化线程标识
			this.preInstantiationThread.remove();
			// 重置预实例化阶段标志
			this.preInstantiationPhase = false;
		}

		// 如果有未完成的 CompletableFuture,等待它们全部完成
		if (!futures.isEmpty()) {
			try {
				CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();
			} catch (CompletionException ex) {
				// 重新抛出异常
				ReflectionUtils.rethrowRuntimeException(ex.getCause());
			}
		}
		// 触发所有适用的 Bean 的后初始化回调
		for (String beanName : beanNames) {
			// 获取单例实例
			Object singletonInstance = getSingleton(beanName, false);
			// 如果单例实例实现了 SmartInitializingSingleton 接口
			if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
				// 记录启动步骤
				StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				// 调用 afterSingletonsInstantiated 方法
				//这个就是说单例Bean完成初始化之后进行一个额外的操作
				smartSingleton.afterSingletonsInstantiated();
				// 结束启动步骤记录
				smartInitialize.end();
			}
		}
	}

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

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

相关文章

【zlm】 webrtc源码讲解三(总结)

目录 setsdp onwrite ​编辑 play 参考 setsdp onwrite play 参考 【zlm】 webrtc源码讲解_zlm webrtc-CSDN博客 【zlm】 webrtc源码讲解&#xff08;二&#xff09;_webrtc 源码-CSDN博客

电子应用设计方案-56:智能书柜系统方案设计

智能书柜系统方案设计 一、引言 随着数字化时代的发展和人们对知识获取的需求增加&#xff0c;智能书柜作为一种创新的图书管理和存储解决方案&#xff0c;能够提供更高效、便捷和个性化的服务。本方案旨在设计一款功能齐全、智能化程度高的智能书柜系统。 二、系统概述 1. 系…

Spring Boot 性能提升的核武器,速度提升 500%!

虚拟线程是 Java 21 引入的一个新特性&#xff0c;用于简化并发编程。它与传统的操作系统线程相比&#xff0c;具有显著的优势&#xff1a; 轻量级&#xff1a;虚拟线程由 JVM 管理&#xff0c;而非操作系统&#xff0c;因此它们的内存占用和创建成本远低于传统线程。理论上&am…

【5G】5G 无线协议 Radio Protocols(一)

长期演进&#xff08;LTE&#xff09;无线电协议主要设计用于通过扁平架构提供PS服务&#xff0c;相比之前的代际&#xff0c;这代表了一个重大改进&#xff0c;它消除了支持电路交换&#xff08;CS&#xff09;服务和复杂架构中固有的复杂性。许多原始的LTE原则自第8版以来一直…

实现按键按下(低电平)检测到下降沿

按照流程进行编程 步骤1&#xff1a; 初始化函数 包括时基工作参数配置 输入通道配置 更新中断使能 使能捕获、捕获中断及计数器 HAL_TIM_IC_Init(&ic_handle) //时基参数配置 HAL_TIM_IC_ConfigChannel(&ic_handle,&ic_config,TIM_CHANNEL_2) //输…

2024广东省职业技能大赛云计算——私有云(OpenStack)平台搭建

OpenStack搭建 前言 搭建采用双节点安装&#xff0c;即controller控制节点和compute计算节点。 CentOS7 系统选择 2009 版本&#xff1a;CentOS-7-x86_64-DVD-2009.iso 可从阿里镜像站下载&#xff1a;https://mirrors.aliyun.com/centos/7/isos/x86_64/ OpenStack使用竞赛培…

使用ENSP实现NAT(2)

一、NAT的类型 二、静态NAT 1.项目拓扑 2.项目实现 路由器AR1配置&#xff1a; 进入系统视图 sys将路由器命名为AR1 sysname AR1关闭信息中心 undo info-center enable 进入g0/0/0接口 int g0/0/0将g0/0/0接口IP地址配置为192.168.10.254/24 ip address 192.168.10.254 24进…

RNN LSTM Seq2Seq Attention

非端到端&#xff1a; data -》 cleaning -》 feature Engining &#xff08;70%-80%工作 设计特征&#xff09;-》 分类器 -》预测 端到端 End-to-End&#xff1a; data -》 cleaning -》Deep learning&#xff08;表示学习&#xff0c;从数据中学习特征&#xff09; -》…

PHP排序算法:数组内有A~E,A移到C或者C移到B后排序,还按原顺序排序,循环

效果 PHP代码 public function demo($params){function moveNext($arr){$length count($arr);$lastElement $arr[$length - 1];for ($i $length - 1; $i > 0; $i--) {$arr[$i] $arr[$i - 1];}$arr[0] $lastElement;return $arr;}function moveAndReplace($array, $from…

Nginx主要知识点总结

1下载nginx 到nginx官网nginx: download下载nginx&#xff0c;然后解压压缩包 然后双击nginx.exe就可以启动nginx 2启动nginx 然后在浏览器的网址处输入localhost&#xff0c;进入如下页面说明nginx启动成功 3了解nginx的配置文件 4熟悉nginx的基本配置和常用操作 Nginx 常…

如何跟进项目

在跟进项目的过程中&#xff0c;我们需要通过清晰的沟通和高效的执行来确保目标按时达成。简单来说&#xff0c;“如何跟进项目”可归纳为&#xff1a;明确目标和交付物、建立高效沟通机制、持续监控进度与风险、灵活应对变更。尤其是“明确目标和交付物”这一点&#xff1a;当…

获取微信用户openid

附上开发文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html 开发之前,准备事项 一个已认证过的服务号|基本信息配置js域名和网站授权域名配置最后确认当前账号网页授权功能是否开通,没有开通的无法获取到用户授权开发人…

【WRF工具】WRF 模型评估MET(Model Evaluation Tools)

WRF 模型评估MET&#xff08;Model Evaluation Tools&#xff09; METplus 简介WRF 模型评估工具 MET 的安装与使用步骤安装步骤使用步骤 参考 METplus 简介 METplus 是一个增强型的模型评估和验证框架&#xff0c;支持从短期预报&#xff08;如实时警报&#xff09;到长期气候…

ARMS 用户体验监控正式发布原生鸿蒙应用 SDK

作者&#xff1a;杨兰馨&#xff08;楠瑆&#xff09; 背景 2024 年 10 月 22 日&#xff0c;华为正式发布了原生鸿蒙操作系统&#xff08;HarmonyOS NEXT&#xff09;。原生鸿蒙实现了系统底座全部自研&#xff0c;系统的流畅度、性能、安全特性等方面显著提升&#xff0c;也…

云计算HCIP-OpenStack04

书接上回&#xff1a; 云计算HCIP-OpenStack03-CSDN博客 12.Nova计算管理 Nova作为OpenStack的核心服务&#xff0c;最重要的功能就是提供对于计算资源的管理。 计算资源的管理就包含了已封装的资源和未封装的资源。已封装的资源就包含了虚拟机、容器。未封装的资源就是物理机提…

MyBatis-Plus 实用工具:SqlHelper

SqlHelper 是MyBatis-Plus的一款SQL 辅助工具类&#xff0c;提供了一些常用的方法&#xff0c;简便我们的操作&#xff0c;提高开发效率。文档 最常用的是SqlHelper.table(Obj.class) 返回的 TableInfo 对象通常包含以下常用方法&#xff1a; 1. getTableName() 获取表名。示例…

压力测试Jmeter简介

前提条件&#xff1a;要安装JDK 若不需要了解&#xff0c;请直接定位到左侧目录的安装环节。 1.引言 在现代软件开发中&#xff0c;性能和稳定性是衡量系统质量的重要指标。为了确保应用程序在高负载情况下仍能正常运行&#xff0c;压力测试变得尤为重要。Apache JMeter 是一…

QT6 Socket通讯封装(TCP/UDP)

为大家分享一下最近封装的以太网socket通讯接口 效果演示 如图&#xff0c;界面还没优化&#xff0c;后续更新 废话不多说直接上教程 添加库 如果为qmake项目中&#xff0c;在.pro文件添加 QT network QT core gui QT networkgreaterThan(QT_MAJOR_VERS…

函数指针的作用

函数指针的主要作用&#xff0c;就是用来选择不同的调度函数&#xff0c;来满足特殊需求。它的优点&#xff0c;使程序设计更加灵活。缺点&#xff1a;初学者很难理解函数指针&#xff0c;从而引起程序的可读性不高。 1、使用函数指针选择调度函数 #include "stm32f10x.…

DateRangePickerDialog组件的用法

文章目录 概念介绍使用方法示例代码我们在上一章回中介绍了DatePickerDialog Widget相关的内容,本章回中将介绍DateRangePickerDialog Widget.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在这里说的DateRangePickerDialog是一种弹出窗口,只不过窗口的内容固定显示为…