SPRING09_ Bean后置处理器创建过程、SmartInstantiationAwareBeanPostProcessor预测方法调用

news2024/11/16 23:56:49

文章目录

  • ①. Bean后置处理器创建过程
  • ②. SmartInstantiationAwareBeanPostProcessor预测方法调用

①. Bean后置处理器创建过程

  • ①. 坏境准备,在BeanPostProcessor的无参构造器、postProcessBeforeInitialization以及postProcessAfterInitialization打上断点.以xml的方式启动容器
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
  • ②. 注册所有的Bean的后置处理器,该方法在finishBeanFactoryInitialization方法之前执行

在这里插入图片描述在这里插入图片描述

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
	    ......
		//BeanFactory第一次开始创建的时候
		// 工厂创建:告诉子类去刷新自己内部的工厂,BeanFactory第一次开始创建的时候获取刷新好的bean工厂
		// 这里xml解析逻辑,也就是xml在这解析完之后,所以bean的定义信息就有了,也就是说BeanFactory第一次开始创建的时候,有xml解析逻辑
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			// 工厂增强:执行所有的BeanFactory后置增强器,利用BeanFactory对工厂进行增强或修改
			// 解释下:在finishBeanFactoryInitialization方法之前执行增强逻辑,可以在bean没有创建的时候,就对bean对象进行增强处理(配置类也会在这里解析)
			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors(beanFactory);

			// 注册所有的Bean的后置处理器 Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();
			......
}

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
  • ③. PostProcessorRegistrationDelegate类中的方法代理了所有的后置增强、相当于后置处理器的管理员
    在这里插入图片描述
  • ⑤. 解析registerBeanPostProcessors方法前面代码
    在这里插入图片描述
public static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	// [1]. 获取到容器中所有的BeanPostProcessor Bean的后置处理器
	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.
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// 这里还加了一个Bean的检查处理器

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 实现了优先级接口的
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();// 内部用的
	List<String> orderedPostProcessorNames = new ArrayList<>();// 实现了排序接口的
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();// 没有实现排序接口的
	for (String ppName : postProcessorNames) {
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 获取所有实现了优先级的PriorityOrdered
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);// 获取到了之后加入到优先级集合中
			if (pp instanceof MergedBeanDefinitionPostProcessor) {//如果处理是MergedBeanDefinitionPostProcessor
				internalPostProcessors.add(pp);// 将其加入到内置处理器
			}
		}
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { // bean是否为Ordered排序的
			orderedPostProcessorNames.add(ppName);// 加入排序集合中
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);// 否则加入不是排序集合中
		}
	}

	// First, register the BeanPostProcessors that implement PriorityOrdered.
	// [1]. 首先注册实现了所有PriorityOrdered(优先级)接口的后置处理器
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Next, register the BeanPostProcessors that implement Ordered.
	// [2]. 接下来注册所有实现了Ordered(排序)接口的后置处理器
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	// 排序后执行
	sortPostProcessors(orderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

	// Now, register all regular BeanPostProcessors.
	// [3]. 最后,注册所有普通的BeanPostProcessors
	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);
		}
	}
	.....
}
  • ⑥. 从容器中获取到BeanPostProcessor组件
  1. 这里会遍历,可以看到集合中有4条记录
  2. 会分别去getBean,获取到这四个类型的Bean
  3. 这四个对象会分别调用无参构造器进行初始化处理
// Now, register all regular BeanPostProcessors.
// [3]. 最后,注册所有普通的BeanPostProcessors
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,Step into进去看看
    在这里插入图片描述

  • ⑧. 工厂提前保存所有增强器,方便在后面创建Bean的时候直接使用


/**保存所有的Bean的后置增强器 BeanPostProcessors to apply. */
private final List<BeanPostProcessor> beanPostProcessors = new BeanPostProcessorCacheAwareList();

private static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

	if (beanFactory instanceof AbstractBeanFactory) {
		// 所谓的注册就是将后置处理器保存到beanPostProcessors集合中 Bulk addition is more efficient against our CopyOnWriteArrayList there
		((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
	}
	else {
		for (BeanPostProcessor postProcessor : postProcessors) {
			beanFactory.addBeanPostProcessor(postProcessor);
		}
	}
}

public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors) {
	this.beanPostProcessors.removeAll(beanPostProcessors);
	this.beanPostProcessors.addAll(beanPostProcessors);
}
  • ⑨. 至此,注册四个后置处理器就结束了
    在这里插入图片描述

②. SmartInstantiationAwareBeanPostProcessor预测方法调用

  • ①. 接着上面的断点放行,可以看到来到了SmartInstantiationAwareBeanPostProcessor的predictBeanType方法,下面我们来进行具体的分析

在这里插入图片描述

  • ②. 容器12大步 - 注册监听器,Spring时间监听机制在这里开始初始化
    在这里插入图片描述
  • ③. 获取ApplicationListener在IOC容器在bean注册的名字
    在这里插入图片描述
protected void registerListeners() {
	// Register statically specified listeners first.
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	//获取ApplicationListener在IOC容器在bean注册的名字 uninitialized to let post-processors apply to them!
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);// 获取所有的容器中的监听器名字,并保存他们的名字
	}

	// Publish early application events now that we finally have a multicaster...
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

@Override// 获取某个类型的组件在容器中的所有名字
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
	assertBeanFactoryActive();
	return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
  • ④. Spring底层获取某个类型是先拿到所有的beanDefinitionNames名称集合,遍历这个名称集合,再通过mergedBeanDefinitions去获取到具体的BeanDefinition的信息,进行获取到类型(这个方法很笨)
    因为Spring没有直接保存Class - name[]定义信息的map

在这里插入图片描述

在这里插入图片描述

// 获取某一个组件在容器中的名字。
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
	List<String> result = new ArrayList<>();

	//因为Spring没有直接保存Class - name定义信息。只能先拿出beanName,再看是否是指定的类型 Check all bean definitions.
	for (String beanName : this.beanDefinitionNames) {
		// Only consider bean as eligible if the bean name is not defined as alias for some other bean.
		if (!isAlias(beanName)) {
			try {
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// Only check bean definition if it is complete.
				if (!mbd.isAbstract() && (allowEagerInit ||
						(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
								!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
					boolean isFactoryBean = isFactoryBean(beanName, mbd);//是不是FactoryBean
					BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
					boolean matchFound = false;
					boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
					boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
					if (!isFactoryBean) {
						if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
							// 只要是没有创建组件的,都会进来这里,这里是cat2进来了,这是因为其他Spring组件在前面都已经创建了,比如后置处理器等
							matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);// 是否类型匹配
  • ⑤. isTypeMatch方法可以通过后置处理器可以返回自定义的类型
    在这里插入图片描述

  • ⑥. 调用我们自己实现了SmartInstantiationAwareBeanPostProcessor接口的predictBeanType方法
    在这里插入图片描述

protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
	Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
	// Apply SmartInstantiationAwareBeanPostProcessors to predict the
	// eventual type after a before-instantiation shortcut.
	if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class;
		for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
			Class<?> predicted = bp.predictBeanType(targetType, beanName);
			if (predicted != null &&
					(!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) {
				return predicted;
			}
		}
	}
	return targetType;
}
  • ⑦. 细节点:为什么这里是传了一个cat2来了呢?
  1. 这是因为这个方法可以改变返回的类型,我们在进行到执行registerListeners方法的时候,其他的组件(比如myBeanPostProcessor)已经完2. 成了组件的创建,我们自定义的Cat2还没有完成创建
  2. 这里会把没有完成创建的实列都进行走predictBeanType方法
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

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

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

相关文章

秋招突击——8/15——新作{最大子数组和、合并区间、转轮数组、除自身以外的数组的乘积}

文章目录 引言新作最大子数组和个人实现参考实现 合并区间个人实现短板补充——自定义排序标准 参考实现 转轮数组最终实现 除自身以外数组的乘积个人实现 总结 引言 以前刷题的方式方法有问题&#xff0c;花太多时间了&#xff0c;应该先过一遍&#xff0c;然后再针对特定的题…

第一百九十四节 Java集合教程 - Java优先级队列

Java集合教程 - Java优先级队列 优先级队列是其中每个元素具有相关联的优先级的队列。具有最高优先级的元素将从队列中删除。 PriorityQueue 是一个实现类对于Java Collection Framework中的无界优先级队列。 我们可以使用在每个元素中实现的 Comparable 接口作为其优先事项。…

C# OnnxRuntime YoloV5 Demo

目录 效果 模型信息 项目 代码 Form1.cs YoloV5.cs 下载 效果 模型信息 Model Properties ------------------------- --------------------------------------------------------------- Inputs ------------------------- name&#xff1a;images tensor&#xff1a…

机器学习/人工智能中的学习证明

一、说明 在进行任何数学发展之前&#xff0c;我们必须首先了解学习的基础以及它如何与错误的概念密切相关。关于代价函数&#xff0c;它的工作原理是梯度下降原理。本文将回顾梯度下降原理。 二、假想的厨师 想象一下&#xff0c;在任何一天&#xff0c;你决定复制你在一家著名…

8.13 Day19 Windows服务器(Windows service 2008 R2)上域的搭建 (1)

域服务器&#xff08;DC&#xff09;&#xff1a;安装了活动目录服务的服务器就称为DC。 将三台设备配置在同一网络中&#xff0c;此处将外部网络隔离开&#xff0c;只将他们放在局域网中 服务端网络配置&#xff0c;此时与外部网络彻底隔绝开&#xff0c;且已无法和主机通信&…

XSS game复现(DOM型)

目录 1.Ma Spaghet! 2.Jefff 3.Ugandan Knuckles 4.Ricardo Milos 5.Ah Thats Hawt 6.Ligma 7.Mafia 8.Ok, Boomer 1.Ma Spaghet! 通过简单的尝试发现传递参数可以直接进入h2标签 接下来我们尝试传入一个alert(1) 可以看到并没有触发。原因是在innerHTML中官方禁用了sc…

二进制安装php

下载php二进制包&#xff1a; 官网地址&#xff1a;https://www.php.net/releases/ PHP: Releaseshttps://www.php.net/releases/在里边可以选择自己要下载的包进行下载&#xff1b; 下载完成后进行解压&#xff1a; tar xvzf php-7.3.12.tar.gz 解压后 进入目录进行预编…

xss案例

首先进入XSS Game - Learning XSS Made Simple! | Created by PwnFunction打开环境 Ma Spaghet 在script里面给使用get传参给somdbody传一个值&#xff0c;若没有传值&#xff0c;默认传SomebodyToucha Ma Spaghet!,赋值给spaghet,放在h2标签中&#xff0c;spaghet后会有一个in…

Linux根目录下的各个目录的用途介绍

在Linux系统中&#xff0c;我们可以通过cd /命令进入根目录&#xff0c;然后ls -l(或者ll命令)即可查看根下目前的目录情况&#xff1a; 这些不同目录的用途说明如下&#xff1a; /bin&#xff1a;包含基本命令文件&#xff0c;如ls、cp等&#xff0c;这个文件中的文件都是可执…

基于协同过滤算法的黔醉酒业白酒销售系统_p091v--论文

TOC springboot349基于协同过滤算法的黔醉酒业白酒销售系统_p091v--论文 绪论 1.1背景及意义 中国经济快速发展&#xff0c;人均GDP逐年上涨&#xff0c;非生活必须品的消费比重也随之增加 &#xff0c;酒类销售额度&#xff0c;尤其是酱香型白酒销售额近些年可谓发展迅猛&…

STM32通过I2C硬件读写MPU6050

目录 STM32通过I2C硬件读写MPU6050 1. STM32的I2C外设简介 2. STM32的I2C基本框图 3. STIM32硬件I2C主机发送流程 10位地址与7位地址的区别 7位主机发送的时序流程 7位主机接收的时序流程 4. STM32硬件与软件的波形对比 5. STM32配置硬件I2C外设流程 6. STM32的I2C.h…

Hadoop如何搭建计算和存储节点分离

在业内存在着一种看起来比较离谱的搭建方式&#xff0c;叫计算节点与存储节点分离&#xff0c;说它比较离谱&#xff0c;是因为hadoop架构本身不直接支持将这两者分开&#xff0c;因为hadoop本身的一大优势就是计算本地化&#xff0c;这种分开搭建的方式抛弃了这种优势&#xf…

Linux 软件编程学习第十五天

1.TCP粘包问题&#xff1a; TCP发送数据是连续的&#xff0c;两次发送的数据可能粘连成一包被接收到 1.解决粘包问题方法&#xff1a; 1.接收指定长度&#xff1a;&#xff08;不稳定&#xff09; 发送5个字节 接收5个字节 2.睡眠&#x…

用户画像实时标签数据处理流程图

背景 在用户画像中&#xff0c;有一类实时标签&#xff0c;我们既要它能够实时的对外提供数据统计&#xff0c;也要保存到大数据组件中用于后续的对数&#xff0c;圈选的逻辑&#xff0c;本文就看一下用户画像的实时标签的数据流转图 实时标签数据流转图 首先我们肯定是要使…

GoMail发送邮件的性能优化策略有哪些方法?

GoMail发送邮件如何配置服务器&#xff1f;GoMail发信功能如何&#xff1f; GoMail是一款广受欢迎的Go语言邮件发送库&#xff0c;具备高效、易用等优点&#xff0c;但在高并发场景下&#xff0c;GoMail发送邮件的性能优化显得尤为重要。AokSend将探讨几种有效的GoMail发送邮件…

图像数据处理14

三、空域滤波 3.3 统计排序滤波器 统计排序滤波器属于非线性空域滤波器&#xff0c;常见的统计排序滤波器有中值滤波器、最大值滤波器、最小值滤波器。 中值滤波器、最大值滤波器和最小值滤波器是三种常见的统计排序滤波器&#xff0c;它们在图像处理和信号处理中发挥着重要…

WUP-MY-LABEL-PRINTER 旻佑热敏打印机标签打印uniapp插件使用说明

插件地址&#xff1a;WUP-MY-LABEL-PRINTER 旻佑热敏打印机标签打印安卓库 简介 本插件主要用于旻佑热敏打印机打印标签&#xff0c;不支持票据打印。适用于旻佑的各型支持标签打印的热敏打印机。本插件开发时使用的打印机型号为MY-805嵌入式面板打印机&#xff0c;其他型号请…

Cisco交换机SSH使用RSA公钥免密登录(IOS与Nexus,服务器以RHEL8为例)

目录 需求实验步骤0. 实验环境1. Linux2. CiscoIOS基础设置保存密钥登陆测试 3. CiscoNexus基础配置保存密钥登陆测试 需求 在实际工作中&#xff0c;常会遇到自动化的需求&#xff0c;那么在自动采集、配置等对网络设备的自动化需求中&#xff0c;不可避免的会遇到需要登录-&…

tensorboard显示一片空白解决方案

OK艾瑞巴蒂 不知道看这个视频几个小土堆过来的&#xff0c;今天已经发了一篇博文探讨快速下载tensorboard了 下面用的时候叒出现问题了 from torch.utils.tensorboard import SummaryWriter writer SummaryWriter("logs")# writer.add_image() # Yx for i in range…

实时手势识别(1)- 基于手部检测+手部分类

目录 前言 1.实现效果 2.非端到端实现的原因 3.分类网络与数据准备 4.训练结果 5.测试结果 6.训练代码 7.训练日志 7.1ResNet18训练日志 7.2ShuffleNet_v2训练日志 前言 利用YOLOv8获取手部区域&#xff0c;然后对手部区域进行分类&#xff0c;实现手势识别。 本文使…