认识BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor
本文分享自华为云社区《Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPos》,作者: 砖业洋__ 。
在Spring框架中,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实例化之前完成。
1.定义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 {
@Override
public String toString() {
return "Blue{" + "label='" + label + '\'' + "}";
}
}
package com.example.demo.bean;
import org.springframework.stereotype.Component;
@Component
public class Yellow extends Tint {
@Override
public String toString() {
return "Yellow{" + "label='" + label + '\'' + "}";
}
}
2.创建后置处理器
思路是在后置处理器中,我们可以获取到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 处理过程中的异常。
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 遍历所有bean的名字
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
// 检查bean的类名是否非空,且其父类是Tint
if (beanDefinition.getBeanClassName() != null &&
ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), this.getClass().getClassLoader())
.getSuperclass().equals(Tint.class)) {
// 添加或更新(如果属性已存在)label属性的值
beanDefinition.getPropertyValues().add("label", "postProcessBeanFactory_" + beanName);
}
}
}
}
3.运行测试
启动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的属性。

4.替代方法
我们也可以使用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 如果在处理过程中出现错误。
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Tint) {
Tint tint = (Tint) bean;
tint.setLabel("postProcessAfterInitialization_" + beanName);
}
return bean;
}
}
运行结果:

5.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实例设置属性。
1.声明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 {
@Override
public String toString() {
return "Apple{" + "type='" + type + '\'' + "}";
}
}
package com.example.demo.bean;
public class Orange extends Fruit {
@Override
public String toString() {
return "Orange{" + "type='" + type + '\'' + '}';
}
}
Orange类没有标注@Component注解,Spring的组件扫描功能默认不会为其创建bean,这个例子中会在OrangeRegisterPostProcessor 里动态创建。
2.编写后置处理器
使用后置处理器来注册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 {
@Override
public 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);
}
}
@Override
public 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 {
@Override
public 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);
}
}
}
3.测试运行
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 进行定制化处理,但它们的关注点和应用时机不同。
1.BeanFactoryPostProcessor:
- 功能: 允许我们在 Spring 容器实例化任何 bean 之前读取 bean 的定义(bean 的元数据)并进行修改。
- 作用时机: 它会在 BeanFactory 的标准初始化之后被调用,此时,所有的 bean 定义已经被加载到容器中,但还没有实例化任何 bean。此时我们可以添加、修改或移除某些 bean 的定义。
- 常见应用: 动态修改 bean 的属性、改变 bean 的作用域、动态注册新的 bean 等。
- 示例接口方法:void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
2.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 的定义进行定制处理。但它们的应用时机和功能上存在一些不同。
1.BeanFactoryPostProcessor:
- 功能: 允许我们在 Spring 容器实例化任何 bean 之前读取 bean 的定义 (BeanDefinition) 并进行修改。
- 作用时机: 在所有的 bean 定义都被加载、但 bean 实例还未创建的时候执行。
- 常见应用: 修改已加载到容器中的 bean 定义的属性,例如更改某个 bean 的作用域、属性值等。
- 主要方法: void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
2.BeanDefinitionRegistryPostProcessor:
- 功能: 扩展了 BeanFactoryPostProcessor,提供了一个新的方法来修改应用程序的上下文的 bean 定义。此外,还可以动态注册新的 bean 定义。
- 作用时机: 它也是在所有 bean 定义被加载后执行,但在 BeanFactoryPostProcessor 之前。
- 常见应用: 动态注册新的 bean 定义、修改或移除已有的 bean 定义。
- 主要方法: void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
总结:
- BeanFactoryPostProcessor 主要是用来修改已经定义的 bean 定义,而不是注册新的 bean。
- BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的扩展,并提供了额外的能力来动态地注册、修改、移除 bean 定义。
在 Spring 容器的启动过程中,首先执行的是 BeanDefinitionRegistryPostProcessor 的方法,之后才是 BeanFactoryPostProcessor 的方法。
认识BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的更多相关文章
- spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
更多文章点击--spring源码分析系列 主要分析内容: 一.BeanFactoryPostProcessor.BeanDefinitionRegistryPostProcessor简述与demo示例 ...
- 003-Spring4 扩展分析-spring类初始化@PostConstruct > InitializingBean > init-method、ApplicationContext、BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
一.spring类初始化@PostConstruct > InitializingBean > init-method InitializingBean接口为bean提供了初始化方法的方式 ...
- 【spring源码分析】BeanDefinitionRegistryPostProcessor解析
一.自定义BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProces ...
- 【spring源码分析】BeanDefinitionRegistryPostProcessor接口可自定义bean加入IOC
自定义BeanDefinitionRegistryPostProcessor BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcesso ...
- Spring-IOC 扩展点 BeanFactoryPostProcessor及其子接口解析
BeanFactoryPostProcessor 接口的英文描述: Allows for custom modification of an application context's bean de ...
- Spring扩展点之BeanFactoryPostProcessor
前言 BeanFactoryPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanFactoryPostProcessor { ...
- 45、[源码]-Spring容器创建-执行BeanFactoryPostProcessor
45.[源码]-Spring容器创建-执行BeanFactoryPostProcessor 5.invokeBeanFactoryPostProcessors(beanFactory);执行BeanF ...
- 自定义BeanDefinitionRegistryPostProcessor
自定义BeanDefinitionRegistryPostProcessor 概述 BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProce ...
- 自定义BeanDefinitionRegistryPostProcessor注册bean
自定义BeanDefinitionRegistryPostProcessor 概述 BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProce ...
- Spring官网阅读(六)容器的扩展点(一)BeanFactoryPostProcessor
之前的文章我们已经学习完了BeanDefinition的基本概念跟合并,其中多次提到了容器的扩展点,这篇文章我们就开始学习这方面的知识.这部分内容主要涉及官网中的1.8小结.按照官网介绍来说,容器的扩 ...
随机推荐
- 实战0-1,Java开发者也能看懂的大模型应用开发实践!!!
前言 在前几天的文章<续写AI技术新篇,融汇工程化实践>中,我分享说在RAG领域,很多都是工程上的实践,做AI大模型应用的开发其实Java也能写,那么本文就一个Java开发者的立场,构建实 ...
- 02-RAID技术 学习心得
RAID 术语 扇区:是磁盘中最小的存储单元,向磁盘读写数据时是以扇区为最小单元进行存储 block:block,是由N个扇区组成一个块: 在磁盘相同偏移处横向逻辑分割,就形成了stripee: 一个 ...
- Linux 本地部署私有Stackedit Markdown编辑器远程访问
StackEdit是一个受欢迎的Markdown编辑器,在GitHub上拥有20.7k Star!,它支持将Markdown笔记保存到多个仓库,包括Gitee.GitHub和Gitea.此在线笔记工具 ...
- FSCTF 2023(公开赛道)CRYPTO WP
RSA 1 1.题目信息 提交格式:FSCTF{你所解出的内容} p=1458769258361 q=4556983871563 e=17 求d 2.解题方法 exp from gmpy2 impor ...
- vite介绍
什么是 Vite 借用作者的原话: Vite,一个基于浏览器原生 ES imports 的开发服务器.利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用. ...
- arm架构docker安装nacos
前言 搞了个hk1box,装了armbian系统,想用这个当服务器调试微服务,需要安装nacos.尝试安装非docker版本的nacos,去github下载arm版本的并且放到linux下面,运行的时 ...
- JUC并发编程学习笔记(十七)彻底玩转单例模式
彻底玩转单例模式 单例中最重要的思想------->构造器私有! 恶汉式.懒汉式(DCL懒汉式!) 恶汉式 package single; //饿汉式单例(问题:因为一上来就把对象加载了,所以可 ...
- bad_python
对着正确的pyc文件在010把题目文件的前缀改掉,然后在线反编译得到代码
- Ubuntu 20.04 查看显示器信息
安装 ddcutil apt install ddcutil 输入命令 ddcutil detect --verbose 输出类似如下: Output level: Verbose Reporting ...
- 文心一言 VS 讯飞星火 VS chatgpt (139)-- 算法导论11.4 3题
三.用go语言,考虑一个采用均匀散列的开放寻址散列表.当装载因子为 3/4 和 7/8 时,试分别给出一次不成功查找和一次成功查找的探查期望数上界. 文心一言: 在开放寻址法中,当散列表的装载因子超过 ...