Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
文章目录
- 1. BeanFactoryPostProcessor 概览
- 1.1 解读 BeanFactoryPostProcessor
- 1.2. 如何使用 BeanFactoryPostProcessor
- 2. BeanDefinitionRegistryPostProcessor 深入探究
- 2.1 解读 BeanDefinitionRegistryPostProcessor
- 2.2 BeanDefinitionRegistryPostProcessor 的执行时机
- 2.3. 动态注册 Bean:BeanDefinitionRegistryPostProcessor 实践
- 3. 三种后置处理器的对比
- 4. 总结与洞见
- 4.1. BeanFactoryPostProcessor 与 BeanPostProcessor 的差异
- 4.2. BeanFactoryPostProcessor 与 BeanDefinitionRegistryPostProcessor 的关系
1. BeanFactoryPostProcessor 概览
1.1 解读 BeanFactoryPostProcessor
BeanFactoryPostProcessor位于org.springframework.beans.factory.config包中。它与BeanPostProcessor有相似的核心逻辑,但它们之间的主要区别在于它们所操作的对象。BeanFactoryPostProcessor的主要目的是对Bean的配置元数据进行操作,这意味着它可以影响Bean的初始配置数据。
在Spring IoC容器实例化beans之前,特别是除了BeanFactoryPostProcessor之外的其他beans,BeanFactoryPostProcessor有权利修改这些beans的配置。在Spring中,所有的beans在被完全实例化之前都是以BeanDefinition的形式存在的。BeanFactoryPostProcessor为我们提供了一个机会,使我们能够在bean完全实例化之前调整和修改这些BeanDefinition。对BeanDefinition的任何修改都会影响后续的bean实例化和初始化过程。
1.2. 如何使用 BeanFactoryPostProcessor
来看看BeanFactoryPostProcessor能如何影响BeanDefinition。
假设我们需要为一系列的Tint对象赋值名字,这个名字就是bean的名字,而且要在bean实例化之前完成。
- 定义bean
我们定义一个简单的Tint抽象类以及其两个子类Blue和Yellow:
package com.example.demo.bean;public abstract class Tint {protected String label;public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}
}
package com.example.demo.bean;import org.springframework.stereotype.Component;@Component
public class Blue extends Tint {@Overridepublic String toString() {return "Blue{" + "label='" + label + '\'' + "}";}
}
package com.example.demo.bean;import org.springframework.stereotype.Component;@Component
public class Yellow extends Tint {@Overridepublic String toString() {return "Yellow{" + "label='" + label + '\'' + "}";}
}
- 创建后置处理器
思路是在后置处理器中,我们可以获取到BeanFactory,然后操作其中的BeanDefinition。
package com.example.demo.processor;import com.example.demo.bean.Tint;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;/*** BeanFactory后置处理器,用于设置Tint子类bean的label属性。* label属性的值会设置为"postProcessBeanFactory_" + beanName。*/
@Component
public class TintLabelSetterFactoryPostProcessor implements BeanFactoryPostProcessor {/*** 在所有BeanDefinition加载完成之后,但bean实例化之前,设置label属性。** @param beanFactory 可配置的bean工厂,可以操作BeanDefinition。* @throws BeansException 处理过程中的异常。*/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 遍历所有bean的名字for (String beanName : beanFactory.getBeanDefinitionNames()) {BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);// 检查bean的类名是否非空,且其父类是Tintif (beanDefinition.getBeanClassName() != null &&ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), this.getClass().getClassLoader()).getSuperclass().equals(Tint.class)) {// 添加或更新(如果属性已存在)label属性的值beanDefinition.getPropertyValues().add("label", "postProcessBeanFactory_" + beanName);}}}
}
- 运行测试
启动Spring容器,查看结果:
package com.example.demo;import com.example.demo.bean.Blue;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class DemoApplication {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.example.demo");Blue blue = ctx.getBean(Blue.class);System.out.println(blue);}}
运行之后,控制台打印Blue对象的label属性,显示后置处理器成功修改了bean的属性。

- 替代方法
我们也可以使用BeanPostProcessor达到BeanFactoryPostProcessor相似的效果:
package com.example.demo.processor;import com.example.demo.bean.Tint;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;/*** TintLabelSetterPostProcessor类是一个BeanPostProcessor的实现,* 它为类型为Tint的bean设置'label'属性。该属性的值将被设置为"postProcessAfterInitialization_"加上bean的名称。* 这里是一个postProcessAfterInitialization方法,它会在bean初始化后,但在返回给调用者之前执行。*/
@Component
public class TintLabelSetterPostProcessor implements BeanPostProcessor {/*** 对bean进行后初始化处理。如果bean是Tint类型,它的'label'属性将被设置。** @param bean 将要处理的bean对象。* @param beanName bean的名称。* @return 可能已经修改过的bean。* @throws BeansException 如果在处理过程中出现错误。*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Tint) {Tint tint = (Tint) bean;tint.setLabel("postProcessAfterInitialization_" + beanName);}return bean;}
}
运行结果:

- BeanPostProcessor 与 BeanFactoryPostProcessor 的对比
| 特点 | BeanPostProcessor | BeanFactoryPostProcessor |
|---|---|---|
| 处理目标 | 主要关注已经实例化的 bean 对象。 | 针对 BeanDefinition,也就是 bean 的元数据或者说是配置信息。 |
| 执行时机 | 两个关键阶段: 1. postProcessBeforeInitialization:在 Spring 完成 bean 的实例化、进行属性注入后,但在 bean 的自定义初始化(如通过@PostConstruct注解定义的方法或init-method方法)之前调用。 2. postProcessAfterInitialization:在 bean 的自定义初始化方法执行后调用 | 在 BeanDefinition 已经完成加载、注册到 BeanDefinitionRegistry后,但在 bean 实例化之前。这一时期主要处理 bean 的元数据。 |
| 可操作的空间 | 可以操作实例化的 bean 对象,如修改属性或包裹生成代理对象。 | 主要用于修改或添加 BeanDefinition 的属性、移除某些 BeanDefinition 等。 |
2. BeanDefinitionRegistryPostProcessor 深入探究
2.1 解读 BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor 是 Spring 容器的一个扩展点,主要用于在 Spring 容器完成对 Bean 的定义信息的加载后、但在它们真正实例化之前,进行额外的操作。
为了更好地理解,让我们用一个图书馆的类比:
想象一个新的图书馆正在组织其图书收藏。这个过程可以分为几个步骤:
-
制定书单:图书馆先列出了所有想要的书的名称和作者,但还没有实际购买书籍。在
Spring中,这就类似于创建BeanDefinition。 -
在这个步骤后,但在图书馆真正购买书籍之前,假设图书馆收到了一个特别的捐赠列表(
BeanDefinitionRegistryPostProcessor)。这个捐赠列表允许图书馆在正式购买书籍之前添加或修改书单。在Spring中,这是使用BeanDefinitionRegistryPostProcessor在实际的bean实例化之前修改bean定义的时机。 -
按书单采购:此时,图书馆会按照更新后的书单进行购书。这个过程在
Spring中类似于bean的实例化和属性填充。
更佳专业化的描述如下:
BeanDefinitionRegistryPostProcessor 是Spring中的一个高级扩展接口,继承自 BeanFactoryPostProcessor。它提供了更为深入的方式来干预bean定义的注册过程。
这个接口定义于 org.springframework.beans.factory.support 包内,它的特殊之处在于,除了能够像 BeanFactoryPostProcessor 那样修改已经注册的bean定义(BeanDefinition),还能向注册中心 BeanDefinitionRegistry 中动态地添加或移除bean定义。
BeanDefinitionRegistryPostProcessor 提供了一个核心方法:postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)。通过该方法,我们可以直接操作 BeanDefinitionRegistry,这是一个专门用于bean定义注册的中心接口。它允许我们直接注册新的bean定义、修改已有的bean定义或者完全移除某些bean定义。
使用这个接口的常见场景包括基于项目的特定条件动态地注册beans,例如,可能只在某些环境中需要的beans,或者基于配置选项动态地选择实现类。
与 BeanFactoryPostProcessor 的关键区别在于其执行时机。BeanDefinitionRegistryPostProcessor 的方法在所有其他 BeanFactoryPostProcessor 方法之前执行,这确保了它可以在其他处理器操作前先注册或修改bean定义。
总的来说,BeanDefinitionRegistryPostProcessor 提供了一种在Spring容器配置解析阶段动态介入的能力,允许我们在其他配置处理器介入之前,进行更为深入的bean定义的调整和优化。
2.2 BeanDefinitionRegistryPostProcessor 的执行时机
执行时机用一张流程图表示如下:

- 加载配置:
Spring从各种来源(如XML文件、Java配置、注解)加载配置信息。 - 解析配置: 根据加载的配置,
Spring创建对应的BeanDefinition。 - 注册BeanDefinition: 解析完成后,
Spring将这些BeanDefinition对象注册到BeanDefinitionRegistry中。 - 执行BeanDefinitionRegistryPostProcessor: 这个后置处理器提供了一个重要的扩展点,允许在所有
BeanDefinition注册完毕后,但在Bean实例化之前进行一些操作。例如:注册新的BeanDefinition、修改或删除现有的BeanDefinition。 - 执行BeanFactoryPostProcessor: 这个后置处理器提供了另一个扩展点,它主要允许查看或修改已经注册的
BeanDefinition。例如,根据某些条件更改Bean的作用域或属性值。 - 实例化Bean: 这是将
BeanDefinition转换为实际的Bean实例的过程。 - 依赖注入: 在这一步,
Spring框架会按照BeanDefinition的描述为bean实例注入所需的依赖。 - Bean初始化: 在所有依赖都注入后,特定的初始化方法(如通过
@PostConstruct指定的)将会被调用,完成Bean的最后设置。 - 执行BeanPostProcessor的方法:
BeanPostProcessor提供了拦截的能力,允许在Bean初始化阶段结束之前和之后进行操作。 - Bean完全初始化: 在此阶段,
Bean完全初始化并准备好被应用程序使用。
虚线解释:
- 执行BeanDefinitionRegistryPostProcessor 到 执行BeanFactoryPostProcessor 之间的虚线:
注册/修改/删除BeanDefinition: 在执行 BeanDefinitionRegistryPostProcessor 的过程中,除了执行已定义的操作外,还提供了一个重要的扩展点,允许我们注册新的 BeanDefinition、修改或删除已有的 BeanDefinition。这为我们提供了一个机会在后续的 BeanFactoryPostProcessor 执行前改变或增强我们的 bean 定义。
- 执行BeanFactoryPostProcessor 到 实例化Bean 之间的虚线:
查看/修改BeanDefinition: BeanFactoryPostProcessor 允许我们查看或修改已注册的 BeanDefinition。这意味着在 bean 实例化之前,我们还有最后一次机会修改 bean 的定义或属性。例如,根据某些运行时环境或条件更改 bean 的作用域。
2.3. 动态注册 Bean:BeanDefinitionRegistryPostProcessor 实践
假设有一个Fruit的抽象水果类,以及两个具体的水果类:Apple和Orange。在最初,IOC容器中只注册了Apple,没有Orange。我们将使用BeanDefinitionRegistryPostProcessor来注册一个Orange的实例,然后利用BeanFactoryPostProcessor来为所有的Fruit实例设置属性。
- 声明Bean
首先,我们定义抽象类Fruit及其属性:
package com.example.demo.bean;public abstract class Fruit {protected String type;public String getType() {return type;}public void setType(String type) {this.type = type;}
}
package com.example.demo.bean;import org.springframework.stereotype.Component;@Component
public class Apple extends Fruit {@Overridepublic String toString() {return "Apple{" + "type='" + type + '\'' + "}";}
}
package com.example.demo.bean;public class Orange extends Fruit {@Overridepublic String toString() {return "Orange{" + "type='" + type + '\'' + '}';}
}
Orange类没有标注@Component注解,Spring的组件扫描功能默认不会为其创建bean,这个例子中会在OrangeRegisterPostProcessor 里动态创建。
- 编写后置处理器
使用后置处理器来注册Orange:
package com.example.demo.processor;import com.example.demo.bean.Orange;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;/*** OrangeRegisterPostProcessor是一个BeanDefinitionRegistryPostProcessor。* 它的主要作用是检查IOC容器中是否已经包含了名为"orange"的bean定义。* 如果没有,它会动态创建一个Orange类的bean定义并注册到容器中。*/
@Component
public class OrangeRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {System.out.println("postProcessBeanDefinitionRegistry in OrangeRegisterPostProcessor started.");if (!registry.containsBeanDefinition("orange")) {BeanDefinition orangeDefinition = BeanDefinitionBuilder.genericBeanDefinition(Orange.class).getBeanDefinition();registry.registerBeanDefinition("orange", orangeDefinition);}}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {System.out.println("postProcessBeanFactory in OrangeRegisterPostProcessor started.");}
}
为所有的Fruit实例设置属性:
package com.example.demo.processor;import com.example.demo.bean.Fruit;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;/*** FruitTypeSetterPostProcessor是一个BeanFactoryPostProcessor。* 它的主要作用是为所有Fruit类型的bean(Apple和Orange)设置"type"属性。* 其中,属性的值与bean的名称相同。*/
@Component
public class FruitTypeSetterPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {System.out.println("postProcessBeanFactory in FruitTypeSetterPostProcessor started.");String[] fruitNames = beanFactory.getBeanNamesForType(Fruit.class);for (String name : fruitNames) {BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);beanDefinition.getPropertyValues().add("type", name);}}
}
- 测试运行
package com.example.demo;import com.example.demo.bean.Apple;
import com.example.demo.bean.Orange;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class DemoApplication {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.example.demo");Apple apple = context.getBean(Apple.class);System.out.println(apple);Orange orange = context.getBean(Orange.class);System.out.println(orange);}
}
运行结果:

这段代码展示了如何使用BeanDefinitionRegistryPostProcessor来动态地注册beans和为其设置属性。
3. 三种后置处理器的对比
| 后置处理器 | 处理目标 | 执行时机 | 主要操作 |
|---|---|---|---|
| BeanPostProcessor | 针对已经实例化但未完全初始化的 bean 对象 | 在bean的初始化过程中,具体是在bean生命周期的初始化方法前后执行 | 主要用于在bean初始化前后进行操作,如修改bean属性、生成代理对象等。 |
| BeanFactoryPostProcessor | 主要针对BeanDefinition,即bean的配置元数据 | 所有的 BeanDefinition 已加载到 BeanDefinitionRegistry 且已完成注册。此时机允许我们在bean真正实例化和初始化之前,对其配置元数据(即 BeanDefinition)进行修改或添加操作 | 修改已注册的 BeanDefinition。此操作可能包括修改属性、改变类的定义或者进行其他任何与 BeanDefinition 相关的操作 |
| BeanDefinitionRegistryPostProcessor | 主要针对BeanDefinitionRegistry,该处理器可以处理来自各种配置源(如配置文件、Java配置等)的BeanDefinition | 在所有 BeanDefinition 被加载和注册之后,但在其他 BeanFactoryPostProcessor 执行之前 | 向 BeanDefinitionRegistry 注册、修改或移除 BeanDefinition |
4. 总结与洞见
4.1. BeanFactoryPostProcessor 与 BeanPostProcessor 的差异
BeanFactoryPostProcessor 和 BeanPostProcessor 都是 Spring 框架中为了增强容器的处理能力而提供的扩展点。它们都可以对 Bean 进行定制化处理,但它们的关注点和应用时机不同。
- BeanFactoryPostProcessor:
-
功能: 允许我们在
Spring容器实例化任何bean之前读取bean的定义(bean的元数据)并进行修改。 -
作用时机: 它会在
BeanFactory的标准初始化之后被调用,此时,所有的bean定义已经被加载到容器中,但还没有实例化任何bean。此时我们可以添加、修改或移除某些bean的定义。 -
常见应用: 动态修改
bean的属性、改变bean的作用域、动态注册新的bean等。 -
示例接口方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
- BeanPostProcessor:
-
功能: 允许我们在
Spring容器实例化bean之后对bean进行处理,提供了一种机会在bean的初始化前后插入我们的自定义逻辑。 -
作用时机: 它在
bean的生命周期中的两个时间点被调用,即在自定义初始化方法(如@PostConstruct,init-method)之前和之后。 -
常见应用: 对特定的
bean实例进行一些额外处理,如进行某种代理、修改bean的状态等。 -
示例接口方法:
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; 和Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
总结:
-
BeanFactoryPostProcessor主要关注于整个容器的配置,允许我们修改bean的定义或元数据。它是容器级别的。 -
BeanPostProcessor主要关注于bean的实例,允许我们在初始化前后对bean实例进行操作。它是bean级别的。
4.2. BeanFactoryPostProcessor 与 BeanDefinitionRegistryPostProcessor 的关系
BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 都是 Spring 中提供的两个重要的扩展点,它们都允许我们在 Spring 容器启动过程中对 Bean 的定义进行定制处理。但它们的应用时机和功能上存在一些不同。
- BeanFactoryPostProcessor:
-
功能: 允许我们在
Spring容器实例化任何bean之前读取bean的定义 (BeanDefinition) 并进行修改。 -
作用时机: 在所有的
bean定义都被加载、但bean实例还未创建的时候执行。 -
常见应用: 修改已加载到容器中的
bean定义的属性,例如更改某个bean的作用域、属性值等。 -
主要方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
- BeanDefinitionRegistryPostProcessor:
-
功能: 扩展了
BeanFactoryPostProcessor,提供了一个新的方法来修改应用程序的上下文的bean定义。此外,还可以动态注册新的bean定义。 -
作用时机: 它也是在所有
bean定义被加载后执行,但在BeanFactoryPostProcessor之前。 -
常见应用: 动态注册新的
bean定义、修改或移除已有的bean定义。 -
主要方法:
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
总结:
-
BeanFactoryPostProcessor主要是用来修改已经定义的bean定义,而不是注册新的bean。 -
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的扩展,并提供了额外的能力来动态地注册、修改、移除bean定义。
在 Spring 容器的启动过程中,首先执行的是 BeanDefinitionRegistryPostProcessor 的方法,之后才是 BeanFactoryPostProcessor 的方法。
欢迎一键三连~
有问题请留言,大家一起探讨学习
----------------------Talk is cheap, show me the code-----------------------
相关文章:
Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
文章目录 1. BeanFactoryPostProcessor 概览1.1 解读 BeanFactoryPostProcessor1.2. 如何使用 BeanFactoryPostProcessor 2. BeanDefinitionRegistryPostProcessor 深入探究2.1 解读 BeanDefinitionRegistryPostProcessor2.2 BeanDefinitionRegistryPostProcessor 的执行时机2.…...
【LeetCode动态规划】详解买卖票I~IV,经典dp题型买
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大利润。…...
【深入探究人工智能】:常见机器学习算法总结
文章目录 1、前言1.1 机器学习算法的两步骤1.2 机器学习算法分类 2、逻辑回归算法2.1 逻辑函数2.2 逻辑回归可以用于多类分类2.3 逻辑回归中的系数 3、线性回归算法3.1 线性回归的假设3.2 确定线性回归模型的拟合优度3.3线性回归中的异常值处理 4、支持向量机(SVM&a…...
设计模式之解释器模式详解及实例
1、解释器设计模式概述: 解释器模式(Interpreter Pattern)是一种设计模式,它主要用于描述如何构建一个解释器以解释特定的语言或表达式。该模式定义了一个文法表示和解释器的类结构,用于解释符合该文法规则的语句。解…...
Nodejs沙箱逃逸--总结
一、沙箱逃逸概念 JavaScript和Nodejs之间有什么区别:JavaScript用在浏览器前端,后来将Chrome中的v8引擎单独拿出来为JavaScript单独开发了一个运行环境,因此JavaScript也可以作为一门后端语言,写在后端(服务端&#…...
No115.精选前端面试题,享受每天的挑战和学习
文章目录 变量提升和函数提升的顺序Event Loop封装 FetchAPI,要求超时报错的同时,取消执行的 promise(即不继续执行)强缓存和协商缓存的区别token可以放在cookie里吗? 变量提升和函数提升的顺序 在JavaScript中&#…...
Elasticsearch:语义搜索 - Semantic Search in python
当 OpenAI 于 2022 年 11 月发布 ChatGPT 时,引发了人们对人工智能和机器学习的新一波兴趣。 尽管必要的技术创新已经出现了近十年,而且基本原理的历史甚至更早,但这种巨大的转变引发了各种发展的“寒武纪大爆炸”,特别是在大型语…...
Flink学习笔记(一)
流处理 批处理应用于有界数据流的处理,流处理则应用于无界数据流的处理。 有界数据流:输入数据有明确的开始和结束。 无界数据流:输入数据没有明确的开始和结束,或者说数据是无限的,数据通常会随着时间变化而更新。 在…...
[Raspberry Pi]如何用VNC遠端控制樹莓派(Ubuntu desktop 23.04)?
之前曾利用VMware探索CentOS,熟悉Linux操作系統的指令和配置運作方式,後來在樹莓派價格飛漲的時期,遇到貴人贈送Raspberry Pi 4 model B / 8GB,這下工具到位了,索性跳過樹莓派官方系統(Raspberry Pi OS),直…...
17.HPA和rancher
文章目录 HPA部署 metrics-server部署HPA Rancher部署Rancherrancher添加集群仪表盘创建 namespace仪表盘创建 Deployments仪表盘创建 service 总结 HPA HPA(Horizontal Pod Autoscaling)Pod 水平自动伸缩,Kubernetes 有一个 HPA 的资源&…...
VS2022远程Linux使用cmake开发c++工程配置方法
文章目录 远程连接CMakePresets.json的配置Task.vs.json配置launch.vs.json配置最近使用别人在VS2015上使用visualgdb搭建的linux开发环境,各种不顺手,一会代码不能调转了,一会行号没了,调试的时候断不到正确的位置,取消的断点仍然会进。因此重新摸索了一套使用vs的远程开…...
《强化学习:原理与Python实战》——可曾听闻RLHF
前言: RLHF(Reinforcement Learning with Human Feedback,人类反馈强化学习)是一种基于强化学习的算法,通过结合人类专家的知识和经验来优化智能体的学习效果。它不仅考虑智能体的行为奖励,还融合了人类专家…...
STM32——RTC实时时钟
文章目录 Unix时间戳UTC/GMT 时间戳转换BKP简介BKP基本结构读写BKP备份寄存器电路设计关键代码 RTC简介RTC框图RTC基本结构硬件电路RTC操作注意事项读写实时时钟电路设计关键代码 Unix时间戳 Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日…...
webSocket 开发
1 认识webSocket WebSocket_ohana!的博客-CSDN博客 一,什么是websocket WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽…...
c#设计模式-结构型模式 之 代理模式
前言 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接 引用目标对象,代理对象作为访问对象和目标对象之间的中介。在学习代理模式的时候,可以去了解一下Aop切面编程AOP切面编程_aop编程…...
openpnp - 自动换刀的设置
文章目录 openpnp - 自动换刀的设置概述笔记采用的openpnp版本自动换刀库的类型选择自动换刀设置前的注意事项先卸掉吸嘴座上所有的吸嘴删掉所有的吸嘴设置自动换刀的视觉识别设置吸嘴座为自动换刀 - 以N1为例备注补充 - 吸嘴轴差个0.3mm, 就有可能怼坏吸嘴END openpnp - 自动换…...
《HeadFirst设计模式(第二版)》第十章代码——状态模式
如下图所示,这是一个糖果机的状态机图,要求使用代码实现: 初始版本: package Chapter10_StatePattern.Origin;/*** Author 竹心* Date 2023/8/19**/public class GumballMachine {final static int SOLD_OUT 0;final static int…...
day-25 代码随想录算法训练营(19)回溯part02
216.组合总和||| 思路:和上题一样,差别在于多了总和,但是数字局限在1-9 17.电话号码的字母组合 思路:先纵向遍历第i位电话号码对于的字符串,再横向递归遍历下一位电话号码 93.复原IP地址 画图分析: 思…...
PG逻辑备份与恢复
文章目录 创建测试数据pg_dump 备份pg_restore 恢复pg_restore 恢复并行备份的文件PG 只导出指定函数 创建测试数据 drop database if exists test; create database test ; \c test create table t1(id int primary key); create table t2(id serial primary key, name varch…...
图数据库_Neo4j和SpringBoot整合使用_实战创建明星关系图谱---Neo4j图数据库工作笔记0010
然后我们再来看一下这个明星关系图谱 可以看到这里 这个是原来的startRelation 我们可以写CQL去查询对应的关系 可以看到,首先查询出来以后,然后就可以去创建 我们可以把写的创建明星关系的CQL,拿到 springboot中去执行 可以看到,这里我们先写一个StarRelationRepository,然…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
