Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析

news2024/11/24 19:04:44

文章目录

  • 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之外的其他beansBeanFactoryPostProcessor有权利修改这些beans的配置。在Spring中,所有的beans在被完全实例化之前都是以BeanDefinition的形式存在的。BeanFactoryPostProcessor为我们提供了一个机会,使我们能够在bean完全实例化之前调整和修改这些BeanDefinition。对BeanDefinition的任何修改都会影响后续的bean实例化和初始化过程。

1.2. 如何使用 BeanFactoryPostProcessor

来看看BeanFactoryPostProcessor能如何影响BeanDefinition

假设我们需要为一系列的Tint对象赋值名字,这个名字就是bean的名字,而且要在bean实例化之前完成。

  1. 定义bean

我们定义一个简单的Tint抽象类以及其两个子类BlueYellow:

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 + '\'' + "}";
    }
}
  1. 创建后置处理器

思路是在后置处理器中,我们可以获取到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);
            }
        }
    }
}
  1. 运行测试

启动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的属性。

在这里插入图片描述

  1. 替代方法

我们也可以使用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;
    }
}

运行结果:

在这里插入图片描述

  1. BeanPostProcessor 与 BeanFactoryPostProcessor 的对比
特点BeanPostProcessorBeanFactoryPostProcessor
处理目标主要关注已经实例化的 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

  BeanDefinitionRegistryPostProcessorSpring 容器的一个扩展点,主要用于在 Spring 容器完成对 Bean 的定义信息的加载后、但在它们真正实例化之前,进行额外的操作。

为了更好地理解,让我们用一个图书馆的类比:

想象一个新的图书馆正在组织其图书收藏。这个过程可以分为几个步骤:

  1. 制定书单:图书馆先列出了所有想要的书的名称和作者,但还没有实际购买书籍。在Spring中,这就类似于创建BeanDefinition

  2. 在这个步骤后,但在图书馆真正购买书籍之前,假设图书馆收到了一个特别的捐赠列表(BeanDefinitionRegistryPostProcessor)。这个捐赠列表允许图书馆在正式购买书籍之前添加或修改书单。在Spring中,这是使用BeanDefinitionRegistryPostProcessor在实际的bean实例化之前修改bean定义的时机。

  3. 按书单采购:此时,图书馆会按照更新后的书单进行购书。这个过程在Spring中类似于bean的实例化和属性填充。

更佳专业化的描述如下

  BeanDefinitionRegistryPostProcessorSpring中的一个高级扩展接口,继承自 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 的执行时机

执行时机用一张流程图表示如下:

在这里插入图片描述

  1. 加载配置: Spring从各种来源(如XML文件、Java配置、注解)加载配置信息。
  2. 解析配置: 根据加载的配置,Spring创建对应的BeanDefinition
  3. 注册BeanDefinition: 解析完成后,Spring将这些BeanDefinition对象注册到BeanDefinitionRegistry中。
  4. 执行BeanDefinitionRegistryPostProcessor: 这个后置处理器提供了一个重要的扩展点,允许在所有BeanDefinition注册完毕后,但在Bean实例化之前进行一些操作。例如:注册新的BeanDefinition、修改或删除现有的BeanDefinition
  5. 执行BeanFactoryPostProcessor: 这个后置处理器提供了另一个扩展点,它主要允许查看或修改已经注册的BeanDefinition。例如,根据某些条件更改Bean的作用域或属性值。
  6. 实例化Bean: 这是将BeanDefinition转换为实际的Bean实例的过程。
  7. 依赖注入: 在这一步,Spring 框架会按照 BeanDefinition 的描述为 bean 实例注入所需的依赖。
  8. Bean初始化: 在所有依赖都注入后,特定的初始化方法(如通过@PostConstruct指定的)将会被调用,完成Bean的最后设置。
  9. 执行BeanPostProcessor的方法: BeanPostProcessor提供了拦截的能力,允许在Bean初始化阶段结束之前和之后进行操作。
  10. Bean完全初始化: 在此阶段,Bean 完全初始化并准备好被应用程序使用。

虚线解释:

  • 执行BeanDefinitionRegistryPostProcessor 到 执行BeanFactoryPostProcessor 之间的虚线:

  注册/修改/删除BeanDefinition: 在执行 BeanDefinitionRegistryPostProcessor 的过程中,除了执行已定义的操作外,还提供了一个重要的扩展点,允许我们注册新的 BeanDefinition、修改或删除已有的 BeanDefinition。这为我们提供了一个机会在后续的 BeanFactoryPostProcessor 执行前改变或增强我们的 bean 定义。

  • 执行BeanFactoryPostProcessor 到 实例化Bean 之间的虚线:

  查看/修改BeanDefinition: BeanFactoryPostProcessor 允许我们查看或修改已注册的 BeanDefinition。这意味着在 bean 实例化之前,我们还有最后一次机会修改 bean 的定义或属性。例如,根据某些运行时环境或条件更改 bean 的作用域。

2.3. 动态注册 Bean:BeanDefinitionRegistryPostProcessor 实践

  假设有一个Fruit的抽象水果类,以及两个具体的水果类:AppleOrange。在最初,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 里动态创建。

  1. 编写后置处理器

使用后置处理器来注册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);
        }
    }
}
  1. 测试运行
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 的差异

  BeanFactoryPostProcessorBeanPostProcessor 都是 Spring 框架中为了增强容器的处理能力而提供的扩展点。它们都可以对 Bean 进行定制化处理,但它们的关注点和应用时机不同。

  1. BeanFactoryPostProcessor:
  • 功能: 允许我们在 Spring 容器实例化任何 bean 之前读取 bean 的定义(bean 的元数据)并进行修改。

  • 作用时机: 它会在 BeanFactory 的标准初始化之后被调用,此时,所有的 bean 定义已经被加载到容器中,但还没有实例化任何 bean。此时我们可以添加、修改或移除某些 bean 的定义。

  • 常见应用: 动态修改 bean 的属性、改变 bean 的作用域、动态注册新的 bean 等。

  • 示例接口方法:void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

  1. 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 的关系

  BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor 都是 Spring 中提供的两个重要的扩展点,它们都允许我们在 Spring 容器启动过程中对 Bean 的定义进行定制处理。但它们的应用时机和功能上存在一些不同。

  1. BeanFactoryPostProcessor:
  • 功能: 允许我们在 Spring 容器实例化任何 bean 之前读取 bean 的定义 (BeanDefinition) 并进行修改。

  • 作用时机: 在所有的 bean 定义都被加载、但 bean 实例还未创建的时候执行。

  • 常见应用: 修改已加载到容器中的 bean 定义的属性,例如更改某个 bean 的作用域、属性值等。

  • 主要方法: void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

  1. BeanDefinitionRegistryPostProcessor:
  • 功能: 扩展了 BeanFactoryPostProcessor,提供了一个新的方法来修改应用程序的上下文的 bean 定义。此外,还可以动态注册新的 bean 定义。

  • 作用时机: 它也是在所有 bean 定义被加载后执行,但在 BeanFactoryPostProcessor 之前。

  • 常见应用: 动态注册新的 bean 定义、修改或移除已有的 bean 定义。

  • 主要方法: void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

总结:

  • BeanFactoryPostProcessor 主要是用来修改已经定义的 bean 定义,而不是注册新的 bean

  • BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 的扩展,并提供了额外的能力来动态地注册、修改、移除 bean 定义。

Spring 容器的启动过程中,首先执行的是 BeanDefinitionRegistryPostProcessor 的方法,之后才是 BeanFactoryPostProcessor 的方法。


欢迎一键三连~

有问题请留言,大家一起探讨学习

----------------------Talk is cheap, show me the code-----------------------

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

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

相关文章

Redis+SpringBoot企业版集群实战------【华为云版】

目录 安装 复制及集群 bgsave rdb aof SpringBoot+Redis操作

斯特林近似(Stirling‘s approximation)

斯特林公式(Stirling’s approximation)是一条用来取n的阶乘的近似值的数学公式。一般来说,阶乘的计算复杂度为线性。当要为某些极大的n求阶乘时,常见的方法复杂度不可接受。斯特林公式能够将求解阶乘的复杂度降低到对数级。而且&…

在云服务器上安装Jenkins

说明:Jenkins是一个部署项目的平台,通过Jenkins可以省去从项目开发–>部署项目之间的所有流程,做到代码提交即上线。本文介绍在云服务CentOS上安装Jenkins。 前提 安装Jenkins之前,先要在云服务上安装JDK、Maven、Git&#x…

SpringAOP原理:手写动态代理实现

0、基础知识 AOP我们知道,是在不修改源代码的情况下,为代码添加一些新功能的技术。通过动态代理,可以在不修改原始类代码的前提下,对方法进行拦截和增强。 动态代理常用于在不改变原有业务逻辑的情况下,对方法…

Dockerfile部署LNMP

文章目录 一、项目模拟1. 项目环境2. 服务器环境3. 任务需求 二、Linux 系统基础镜像三、Nginx1. 建立工作目录2. 编写 Dockerfile 脚本3. 准备 nginx.conf 配置文件4. 生成镜像5. 创建自定义网络6. 启动镜像容器7. 验证 nginx 三、Mysql1. 建立工作目录2. 编写 Dockerfile3. 准…

CompletableFuture总结和实践

CompletableFuture被设计在Java中进行异步编程。异步编程意味着在主线程之外创建一个独立的线程,与主线程分隔开,并在上面运行一个非阻塞的任务,然后通知主线程进展,成功或者失败。 一、概述 1.CompletableFuture和Future的区别&…

Centos7查看磁盘和CUP统计信息iostat命令

Centos7查看磁盘和CUP统计信息iostat命令 Centos7内存高|查看占用内存命令 docker实战(一):centos7 yum安装docker docker实战(二):基础命令篇 docker实战(三):docker网络模式(超详细) docker实战(四):docker架构原理 docker实战(五):docker镜像及仓库配置 docker实战(六…

Interlij IDEA 运行 ruoyi 后端项目。错误: 找不到或无法加载主类 com.ruoyi.auth.RuoYiAuthApplication

错误: 找不到或无法加载主类 com.ruoyi.auth.RuoYiAuthApplication 用了 IDEA运行,参考以下issue删除.idea目录也没有用 (官方文档写是用Eclipse运行) 错误: 找不到或无法加载主类 com.ruoyi.auth.RuoYiAuthApplication Issue #I48N2X 若依/RuoYi-C…

Seaborn数据可视化(二)

目录 1.Seaborn风格设置 1.1 主题设置 1.2 轴线设置 1.3 移除轴线 1.4 使用字典传递函数 2.设置绘图元素比例 2.1 设置绘图元素比例paper 2.2 设置绘图元素比例poster 2.3 设置绘图元素比例notebook Seaborn将Matplotlib的参数划分为两个独立的组合,第一组用于…

关于Coursera网站视频无法观看

文章目录 前言找Ip 改hosts验证 前言 众所周知,coursera是很不错的学习网站,但由于国内访问限制,导致我的学习之路举步维艰 在科学上网彻底崩盘后,终于断了我的学习热情(真的很想骂人) 网站只能登入&#…

Qt6之如何为QDialog添加最大化和最小化按钮

在QDialog构造函数中添加以下几行代码: // 设置窗体最大化和最小化Qt::WindowFlags windowFlag Qt::Dialog;windowFlag | Qt::WindowMinimizeButtonHint;windowFlag | Qt::WindowMaximizeButtonHint;windowFlag …

No115.精选前端面试题,享受每天的挑战和学习

文章目录 变量提升和函数提升的顺序Event Loop封装 FetchAPI,要求超时报错的同时,取消执行的 promise(即不继续执行)强缓存和协商缓存的区别token可以放在cookie里吗? 变量提升和函数提升的顺序 在JavaScript中&#…

Cesium之水流模型

关于Primitive。 Primitive和Entity,一般翻译成图元和实体,图元更接近底层,实体是封装后的高级对象,使用更加简便。一般来说,Primitive的使用相对繁琐,相比Entity需要使用者自己初始化更多对象&#xff0c…

LabVIEW开发血液动力学监测仪

LabVIEW开发血液动力学监测仪 心电图和光电容积描记图的缩写分别是心电图、心电图和PPG。都熟悉“心脏病发作”、“心力衰竭”、“冠状动脉疾病”和“中风”等术语,但中很少有人意识到这些疾病都被认为是心血管疾病。心脏病学是一个医学领域,专注于心脏…

树莓牌4B安装Centos8

准备工作 镜像:https://people.centos.org/pgreco/CentOS-Userland-8-stream-aarch64-RaspberryPI-Minimal-4/ 烧制工具:https://www.raspberrypi.com/software/ 初始化 将上述工具烧制好的SD卡插入树莓派,通电。通过网线将树莓派与电脑连…

回归预测 | MATLAB实现PSO-RBF粒子群优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现PSO-RBF粒子群优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现PSO-RBF粒子群优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图&a…

C++初阶——string(字符数组),跟C语言中的繁琐设计say goodbye

前言:在日常的程序设计中,我们会经常使用到字符串。比如一个人的身份证号,家庭住址等,只能用字符串表示。在C语言中,我们经常使用字符数组来存储字符串,但是某些场景(比如插入,删除)下操作起来很…

在线HmacSHA256加密工具--在线获取哈希值又称摘要

具体请前往: 在线计算HmacSha256工具

【Unittest】Unittest接口测试框架开发-以登录模块为例

文章目录 框架结构框架目录结构封装被测试系统接口定义接口测试用例集成测试报告测试数据参数化(一)分析与数据构造(二)基于JSON实现参数化(三)基于数据库实现参数化 框架结构 框架结构包括:被…

Stable Diffusion:使用自己的数据集微调训练LoRA模型

Stable Diffusion:使用自己的数据集微调训练LoRA模型 前言前提条件相关介绍微调训练LoRA模型下载kohya_ss项目安装kohya_ss项目运行kohya_ss项目准备数据集生成关键词模型参数设置预训练模型设置文件夹设置训练参数设置 开始训练LoRA模型TensorBoard查看训练情况 测…