认识Spring 中的BeanPostProcessor

news2024/12/27 11:02:18

关于BeanPostProcessor和BeanFactoryPostProcessors,将分2篇文章来写,这篇文章是对Spring 中BeanPostProcessor进行了总结

先看下大模型对这个类的介绍,随后再看下这两个类的示例,最后看下这两个类的实现。
这两个类从名字看都很类似,见名知意:BeanPostProcessor=Bean后置处理器,BeanFactoryPostProcessors=BeanFactory后置处理器

BeanPostProcessor

在Spring 5.3中,BeanPostProcessor是一个强大的接口,它允许开发者在Spring容器中的bean实例化、配置和初始化前后添加自定义的逻辑处理。以下是关于BeanPostProcessor的详细解释:

1. 作用阶段
BeanPostProcessor在Spring容器完成bean的实例化、配置和其他的初始化前后工作。它提供了两个方法,一个在初始化方法之前执行,另一个在初始化方法之后执行。
2. 主要方法
postProcessBeforeInitialization(Object bean, String beanName):
在bean的初始化方法(如@PostConstruct标记的方法或实现InitializingBean接口中的afterPropertiesSet方法)被调用之前执行。
允许在bean的属性被设置之后,但在初始化之前,对bean进行额外的处理。
postProcessAfterInitialization(Object bean, String beanName):
在bean的初始化方法被调用之后执行。
允许在bean完成初始化后,对其进行修改或返回一个新的对象(尽管这通常不是推荐的做法,因为可能导致意外的行为)。
3. 返回值
这两个方法都不能返回null。如果返回null,那么在后续的操作中可能会遇到空指针异常,或者通过getBean()方法无法获取到bean的实例。
4. 使用方式
要使用BeanPostProcessor,你需要:
实现BeanPostProcessor接口。
实现postProcessBeforeInitialization和postProcessAfterInitialization方法。
将你的BeanPostProcessor实现注册为Spring容器中的一个bean,这样Spring就能够识别并应用它。
5. 排序和优先级
如果在Spring配置中定义了多个BeanPostProcessor,那么默认情况下,Spring容器会根据它们的定义顺序来依次调用。
但是,你可以通过实现Ordered接口或使用@Order、@Priority注解来指定优先级。
6. 应用场景
BeanPostProcessor常被用于AOP(面向切面编程)的自动代理创建、日志记录、安全检查、性能监控等场景。
7. 注意事项
由于BeanPostProcessor能够影响所有bean的初始化过程,因此在使用时需要特别小心,避免引入不必要的复杂性或错误。
如果在postProcessBeforeInitialization或postProcessAfterInitialization方法中修改了bean的状态,需要确保这些修改是预期的,并且不会对其他bean或整个应用程序产生负面影响。
8. 总结
BeanPostProcessor是Spring框架中一个非常强大的工具,它允许开发者在bean的生命周期中的关键阶段插入自定义逻辑。然而,由于其强大的能力,使用时需要谨慎,并确保理解其工作原理和潜在影响。

现在写几个示例来看下是怎么执行的。
我这里定义A、B、C、D 、E、F类,分别如下:
A类

package org.springframework.example.BPP;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 注解方式
 */
@Component
public class A implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		System.out.println("A.postProcessBeforeInitialization");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("A.postProcessAfterInitialization");
		return bean;
	}
}

B类

package org.springframework.example.BPP;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 注解方式,加了顺序
 */
@Component
@Order(0)
public class B implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		System.out.println("B.postProcessBeforeInitialization, order: 0");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("B.postProcessAfterInitialization, order: 0");
		return bean;
	}
}

C类

package org.springframework.example.BPP;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * 注解方式,实现Order
 */
@Component
public class C implements BeanPostProcessor, Ordered {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		System.out.println("C.postProcessBeforeInitialization, order: 1");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("C.postProcessAfterInitialization, order: 1");
		return bean;
	}

	@Override
	public int getOrder() {
		return 1;
	}
}

D类

package org.springframework.example.BPP;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;

/**
 * 注解方式,实现PriorityOrdered
 */
@Component
public class D implements BeanPostProcessor, PriorityOrdered {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		System.out.println("D.postProcessBeforeInitialization, PriorityOrdered: 2");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("D.postProcessAfterInitialization, PriorityOrdered: 2");
		return bean;
	}

	@Override
	public int getOrder() {
		return 2;
	}
}

E类

package org.springframework.example.BPP;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;

/**
 * 注解方式,实现PriorityOrdered
 */
@Component
public class E implements BeanPostProcessor, PriorityOrdered {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		System.out.println("E.postProcessBeforeInitialization, PriorityOrdered: 3");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("E.postProcessAfterInitialization, PriorityOrdered: 3");
		return bean;
	}

	@Override
	public int getOrder() {
		return 3;
	}
}

F类

package org.springframework.example.BPP;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * 注解方式,实现Order
 */
@Component
public class F implements BeanPostProcessor, Ordered {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		System.out.println("F.postProcessBeforeInitialization, order: 4");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		System.out.println("F.postProcessAfterInitialization, order: 4");
		return bean;
	}

	@Override
	public int getOrder() {
		return 4;
	}
}

BeanTest 测试类

package org.springframework.example.BPP;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BeanTest {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext =
				new AnnotationConfigApplicationContext("org.springframework.example.BPP");
	}
}

看下打印结果

D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
C.postProcessBeforeInitialization, order: 1
F.postProcessBeforeInitialization, order: 4
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
C.postProcessAfterInitialization, order: 1
F.postProcessAfterInitialization, order: 4
D.postProcessBeforeInitialization, PriorityOrdered: 2
E.postProcessBeforeInitialization, PriorityOrdered: 3
C.postProcessBeforeInitialization, order: 1
F.postProcessBeforeInitialization, order: 4
D.postProcessAfterInitialization, PriorityOrdered: 2
E.postProcessAfterInitialization, PriorityOrdered: 3
C.postProcessAfterInitialization, order: 1
F.postProcessAfterInitialization, order: 4

初步分析结果,后面再看原因:
1、打印的结果怎么是这样
2、AB为什么没有打印
3、PriorityOrdered 优先级高于Ordered
4、B类的@Order(0)好像没用

带着问题,来分析一下源码:
首先我们的BeanTest类里面的AnnotationConfigApplicationContext,new 的时候内部自带了refresh(),在refresh()里面找到registerBeanPostProcessors(beanFactory),最后在PostProcessorRegistrationDelegate类的registerBeanPostProcessors中打个断点,后面调试用。

在这里插入图片描述
先整体分析一下这段代码:

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
		//上面的注释看,作者意思是这样写很多循环都是有意的,不需要重构
		//获取BeanPostProcessor的实现类的Bean名称集合
		//抛开Spring自带的BeanPostProcessor,这里将会获取到我们自定义的ABCDEF6个类,Spring 自带的BeanPostProcessor,后面再说
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		//这里为什么要+1,我个人估计是因为BeanPostProcessorChecker本身也是一个BeanPostProcessor
		//BeanPostProcessorChecker 用来检测不符合BeanPostProcessors规则的Bean
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		//分别收集PriorityOrdered、Ordered和没有实现排序的BeanPostProcessor和MergedBeanDefinitionPostProcessor类型的Bean
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			//查询指定名称的Bean 是否实现PriorityOrdered 接口,判断的代码也挺复杂,暂且不关心
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//获取BeanPostProcessor的实例
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				//如果是MergedBeanDefinitionPostProcessor类型,该处理器后面再说
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			//如果实现了Ordered接口,则添加到orderedPostProcessorNames集合中
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			//如果没有实现排序接口,则添加到nonOrderedPostProcessorNames集合中
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		//先排序priorityOrderedPostProcessors
		//默认排序规则使用的OrderComparator,优先排序PriorityOrdered的实现类,顺序从小到大排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//注册,就是往beanFactory中的一个List增加BeanPostProcessor
		//这里面又判断了beanFactory 是否是AbstractBeanFactory,关于什么事AbstractBeanFactory,也留着后面讲
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		//注册实现了Ordered的BeanPostProcessors
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			//同样判断了MergedBeanDefinitionPostProcessor
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//同理,排序
		sortPostProcessors(orderedPostProcessors, beanFactory);
		//同理,注册
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		//处理没有实现排序的BeanPostProcessor
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//同理,注册
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		//最后,处理MergedBeanDefinitionPostProcessor
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		//添加ApplicationListenerDetector,其用来注册ApplicationListener类型的bean到上下文中,后面来测试一下
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

下面来调试一下
解释第一个问题,打印结果解密,首先要知道在哪里调用postProcessBeforeInitialization和postProcessAfterInitialization。这里是在通过beanFactory.getBean获取Bean的时候,没有Bean就会创建一个Bean,此时就会调用到,跟进去在AbstractAutowireCapableBeanFactory–>initializeBean 内部进行调用,此处打个断点调式。

在这里插入图片描述
由于几个内置BeanPostProcessor的存在,运行时会多次进入断点,所以我们都跳过,进入applyBeanPostProcessorsBeforeInitialization,查看**getBeanPostProcessors()**的值,此时为几个内置BeanPostProcessor。
在这里插入图片描述
内置Bean自然没有我们的东西,跳过,后面的进入断点次数,不算内置BeanPostProcessor!!!

第二次进入断点,此时beanName 是 e
在这里插入图片描述
此时的getBeanPostProcessors() 还是原来的内置BeanPostProcessor,跳过。

第三次进入断点,此时beanName是“c”
在这里插入图片描述
这时getBeanPostProcessors() 多了D、E,这时继续执行,将打印D、E的postProcessBeforeInitialization日志
在这里插入图片描述
继续往下执行到applyBeanPostProcessorsAfterInitialization,打印

在这里插入图片描述
到这里,Bean C已经处理完了,直接跳过,到下个断点

第四次进入断点是F
在这里插入图片描述
这里的getBeanPostProcessors() 还是DE,没有C,为什么?因为CF都是实现的Ordered,他们都是在一块处理,处理完后才添加到beanPostProcessors中。由前面的代码分析可知。
所以在这里还是打印的DE的日志
在这里插入图片描述

第五次进入断点,beanName是a
在这里插入图片描述
这里开始打印DECF的日志
在这里插入图片描述
第六次进入断点,beanName是b
在这里插入图片描述
到这里所有的类都执行完了

解释一下第二个问题,AB为什么没有被打印。
从上面可知,AB 两个bean的创建在最后,后续没有其他Bean创建,因此没有执行AB 两个BeanPostProcessor的机会。要想打印,单独创建一个普通Bean,来测试一下。
G类

package org.springframework.example.BPP;

import org.springframework.stereotype.Component;

@Component
public class G {
}

在这里插入图片描述
这里发现一个问题,B类的order 是0,怎么会在最后?实际是因为B类被认为是没有实现排序的BeanPostProcessor,也就是 Order(0) 注解在这里没用!!!这也就回答了第四个问题。
在这里插入图片描述

解释第三个问题,PriorityOrdered 优先级高于Ordered,因为代码是先处理的PriorityOrdered 的实现
在这里插入图片描述

最后对于大模型对BeanPostProcessor的介绍中的第五点

5. 排序和优先级
如果在Spring配置中定义了多个BeanPostProcessor,那么默认情况下,Spring容器会根据它们的定义顺序来依次调用。
但是,你可以通过实现Ordered接口或使用@Order、@Priority注解来指定优先级。

是错误的!!!目前只能通过实现Ordered或者PriorityOrdered接口

通过上面的实例测试@Order并没有起作用,@Priority 注解也没法在类上使用,查了一下该注解在javax.annotation-api中。
在这里插入图片描述

作者其他文章推荐:
基于Spring Boot 3.1.0 系列文章

  1. Spring Boot 源码阅读初始化环境搭建
  2. Spring Boot 框架整体启动流程详解
  3. Spring Boot 系统初始化器详解
  4. Spring Boot 监听器详解
  5. Spring Boot banner详解
  6. Spring Boot 属性配置解析
  7. Spring Boot 属性加载原理解析
  8. Spring Boot 异常报告器解析
  9. Spring Boot 3.x 自动配置详解

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

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

相关文章

堆盘子00

题目链接 堆盘子 题目描述 注意点 SetOfStacks应该由多个栈组成&#xff0c;并且在前一个栈填满时新建一个栈 解答思路 将多个栈存储到一个List中&#xff0c;当入栈时&#xff0c;如果List中最后一个栈容量已经达到cap&#xff0c;则需要新建一个栈&#xff0c;将元素推到…

压缩视频在线压缩网站,压缩视频在线压缩工具软件

在数字化时代&#xff0c;视频成为了人们记录和分享生活的重要载体。然而&#xff0c;视频文件一般都非常大&#xff0c;这不仅占据了大量的存储空间&#xff0c;也给视频的传输和分享带来了不便。因此&#xff0c;压缩视频成为了许多人必须掌握的技能。本文将详细介绍如何压缩…

Golang | Leetcode Golang题解之第138题随机链表的复制

题目&#xff1a; 题解&#xff1a; func copyRandomList(head *Node) *Node {if head nil {return nil}for node : head; node ! nil; node node.Next.Next {node.Next &Node{Val: node.Val, Next: node.Next}}for node : head; node ! nil; node node.Next.Next {if…

【一百零九】【算法分析与设计】树状数组求解前缀最大值,673. 最长递增子序列的个数,树状数组求前缀区间最大值

树状数组求解前缀最大值 树状数组可以求解和前缀区间有关的问题,例如前缀和,前缀区间最值. 可以利用 l o g n log_n logn​的时间复杂度快速查找前缀信息. 利用树状数组查询前缀区间中最大值问题. 树状数组下标1位置存储arr数组下标1位置的最大值. 树状数组2位置存储arr数组1,…

树的重心-java

主要通过深度优先搜索来完成树的重心&#xff0c;其中关于树的重心的定义可以结合文字多加理解。 文章目录 前言☀ 一、树的重心☀ 二、算法思路☀ 1.图用邻接表存储 2.图的遍历 3.算法思路 二、代码如下☀ 1.代码如下&#xff1a; 2.读入数据 3,代码运行结果 总结 前言☀ 主…

《PyTorch 实战宝典》重磅发布!

Pytorch 是目前常用的深度学习框架之一&#xff0c;比起 TF 的框架环境配置不兼容&#xff0c;和 Keras 由于高度封装造成的不灵活&#xff0c;PyTorch 无论是在学术圈还是工业界&#xff0c;都相当占优势。 不夸张地说&#xff0c;掌握了 PyTorch &#xff0c;就相当于走上了…

Cloudpods 强大的多云管理平台部署

简介 Cloudpods 是一款简单、可靠的企业IaaS资源管理软件。帮助未云化企业全面云化IDC物理资源&#xff0c;提升企业IT管理效率。 Cloudpods 帮助客户在一个地方管理所有云计算资源。统一管理异构IT基础设施资源&#xff0c;极大简化多云架构复杂度和难度&#xff0c;帮助企业…

[ue5]建模场景学习笔记(5)——必修内容可交互的地形,交互沙(2)

1需求分析&#xff1a; 继续制作可交互沙子内容&#xff0c;前面我们已经让角色在指定区域留下痕迹&#xff0c;那么能否让区域移动起来&#xff0c;这样才能逐步满足角色走到哪里都能产生交互痕迹&#xff0c;满足更大的地图。 2.操作实现&#xff1a; 1.首先建立角色能产生…

12、SpringBoot 源码分析 - 自动配置深度分析五

SpringBoot 源码分析 - 自动配置深度分析五 refresh和自动配置大致流程OnClassCondition的createOutcomesResolver创建结果解析器StandardOutcomesResolver的resolveOutcomes解析结果StandardOutcomesResolver的getOutcomeClassNameFilter的MISSING判断是否没有 ThreadedOutcom…

【YOLOv5/v7改进系列】改进池化层为SPP、SPPF、SPPCSPC

一、导言 池化层&#xff08;Pooling Layer&#xff09;是卷积神经网络&#xff08;Convolutional Neural Networks, CNNs&#xff09;中的一个重要组成部分&#xff0c;主要用于减少输入数据的空间尺寸&#xff08;例如&#xff0c;图像的宽度和高度&#xff09;&#xff0c;…

3D打印随形透气钢:技术革新引领模具制造新潮流

在模具制造领域&#xff0c;透气钢一直扮演着重要角色&#xff0c;它能够有效解决模具困气问题&#xff0c;提高注塑成型的效率和质量。然而&#xff0c;传统的透气钢制造方法受限于工艺和材料&#xff0c;难以满足复杂模具的需求。随着3D打印技术的飞速发展&#xff0c;3D打印…

kettle从入门到精通 第六十四课 ETL之kettle kettle中执行SQL脚本步骤,使用需当心

想真正学习或者提升自己的ETL领域知识的朋友欢迎进群&#xff0c;一起学习&#xff0c;共同进步。文章底部关注我&#xff0c;公众号后台加我微信入群&#xff0c;备注kettle。 1、群里有不定时会有同学反馈执行SQL脚本步骤使用有问题&#xff0c;那么咱们今天一起来学习下该步…

【数据分析基础】实验一 Python运算符、内置函数、序列基本用法

一、实验目的 熟练运用Python运算符。熟练运用Python内置函数。掌握Python的基本输入输出方法。了解lambda表达式作为函数参数的用法。掌握列表、元组、字典、集合的概念和基本用法。了解Python函数式编程模式。 二、实验内容&#xff1a; 1. 在命令模式测试如下命令&#x…

AI-知识库搭建(一)腾讯云向量数据库使用

一、AI知识库 将已知的问答知识&#xff0c;问题和答案转变成向量存储在向量数据库&#xff0c;在查找答案时&#xff0c;输入问题&#xff0c;将问题向量化&#xff0c;匹配向量库的问题&#xff0c;将向量相似度最高的问题筛选出来&#xff0c;将答案提交。 二、腾讯云向量数…

【C++题解】1261. 韩信点兵

问题&#xff1a;1261. 韩信点兵 类型&#xff1a; 题目描述&#xff1a; 韩信有一对士兵&#xff0c;他想知道有多少人&#xff0c;他就让士兵报数&#xff0c;如果按照 1 到 5 报数&#xff0c;最末一个士兵报的数为 1 。 按照 1 到 6 报数&#xff0c;最末一个士兵报的数为…

Oracle EBS AP发票创建会计科目错误:子分类帐日记帐分录未按输入币种进行平衡

系统版本 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状: 提交“创建会计科目”请求提示错误信息如下: 中文报错: 该子分类帐日记帐分录未按输入币种进行平衡。请检查日记帐分录行中输入的金额。 英文报错:The subledger journal entry does not balance i…

【Stable Diffusion】(基础篇二)—— Stable Diffusion图形界面介绍和基本使用流程

本系列笔记主要参考B站nenly同学的视频教程&#xff0c;传送门&#xff1a;B站第一套系统的AI绘画课&#xff01;零基础学会Stable Diffusion&#xff0c;这绝对是你看过的最容易上手的AI绘画教程 | SD WebUI 保姆级攻略_哔哩哔哩_bilibili 在上一篇博客中&#xff0c;我们成功…

数字科技如何助力博物馆设计,强化文物故事表现力?

国际博物馆日是每年为了推广博物馆和文化遗产&#xff0c;而设立的一个特殊的日子&#xff0c;让我们可以深入探讨博物馆如何更好地呈现和保护我们的文化遗产&#xff0c;随着近年来的数字科技发展&#xff0c;其在博物馆领域的应用越来越广泛&#xff0c;它为博物馆提供了新的…

把qml程序制作成安装包(Windows)

先检查一下有没有安装Qt Installer FrameWork 需要用到Qt自带的打包工具&#xff1a; Qt Installer FrameWork&#xff0c;虽然有点拉胯&#xff0c;但是也能用用。一般放在Qt目录下的Tools文件夹下&#xff0c;如果没有看到&#xff0c;就去在线下载器去下载一下。 步骤1 随…

如何在没有密码的情况下解锁iPhone

通常&#xff0c;您可以使用密码、FaceID 或 Touch ID 轻松解锁 iPhone。但是&#xff0c;有时您可能会忘记密码、iPhone 已停用或您的二手手机已锁定。在这种情况下&#xff0c;您必须绕过 iPhone 密码才能访问您的设备。在本文中&#xff0c;我们将向您介绍 5 种经过测试的方…