spring 的invokeBeanFactoryPostProcessors()

news2024/11/25 7:24:48

        在spring启动过程中有个10多个关键的方法其中invokeBeanFactoryPostProcessors()在函数在BeanDefinition完全加载后执行,实现的是spring  bean的后置增强器BeanFactoryPostProcessor。

        BeanFactoryPostProcessor在bean的生命周期中,主要增强的是BeanDefinition对象,对bean的定义信息增加。关键接口为:

postProcessBeanFactory
//实例化并调用所有注册的 BeanFactoryPostProcessor bean,如果给定,则遵守显式顺序。
必须在单一实例化之前调用。	
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

invokeBeanFactoryPostProcessors:

if (beanFactory instanceof BeanDefinitionRegistry) {
   BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
   List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
   List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
   //循环处理实现了BeanFactoryPostProcessor接口的增强器
   for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
      if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
         BeanDefinitionRegistryPostProcessor registryProcessor =
               (BeanDefinitionRegistryPostProcessor) postProcessor;
        //注册更多的bean定义信息
         registryProcessor.postProcessBeanDefinitionRegistry(registry);
         registryProcessors.add(registryProcessor);
      }
      else {
         regularPostProcessors.add(postProcessor);
      }
   }

以:ConfigurationClassPostProcessor为例,实现了接口

BeanDefinitionRegistryPostProcessor继承自:BeanFactoryPostProcessor。

提供了:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}
重写了接口方法:
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		this.registriesPostProcessed.add(registryId);

		processConfigBeanDefinitions(registry);
	}

 

//解析配置类
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

执行解析配置类

	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException

 

 

 扩展:spring的  import就是从这里解析的:

核心接口:

public interface ImportSelector {

	/**
	 * 根据导入 @Configuration 类的 选择并返回应导入AnnotationMetadata的类的名称
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

}
// 处理 @Import 注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
//循环import导入的类				
for (SourceClass candidate : importCandidates) {
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						Class<?> candidateClass = candidate.loadClass();
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
						if (selector instanceof DeferredImportSelector) {
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
//处理实现了接口:ImportSelector的接口
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}

以事务导入为例:AdviceModeImportSelector 实现了接口ImportSelector,重写了selectImports 方法,导入了其余的配置类:TransactionManagementConfigurationSelector

	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}
 

                

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

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

相关文章

企业移动内容管理(MCM)

1.什么是移动内容管理 &#xff08;MCM&#xff09; 移动内容管理 &#xff08;MCM&#xff09; 是指在组织中使用的移动设备上分发和管理企业文件的过程&#xff0c;以确保授权用户可以通过批准的设备安全地访问所需的资源。MCM 允许 IT 管理员在其组织员工使用的智能手机、平…

音频基础知识简述 esp-sr 上手指南

此篇博客先对音频基础知识进行简要叙述&#xff0c;然后帮助读者入门 esp-sr SDK。 1 音频的基本概念 1.1 声音的本质 声音的本质是波在介质中的传播现象&#xff0c;声波的本质是一种波&#xff0c;是一种物理量。 两者不一样&#xff0c;声音是一种抽象的&#xff0c;是声…

Vue学习笔记(6)

6.1 组件 6.1.1 什么是组件 Vue的组件是可复用的Vue实例&#xff0c;它可以封装HTML元素和 CSS样式以及与之相关的JavaScript行为。每个组件都有自己的作用域&#xff0c;因此它可以避免全局作用域中的命名冲突&#xff0c;并且可以方便地在不同的Vue实例中重复使用。组件的结…

2023年武汉安全员C证报考条件、流程、报名时间是什么?启程别

2023年武汉安全员C证报考条件、流程、报名时间是什么&#xff1f;启程别 安全员C建筑施工企业专职安全生产管理人员&#xff0c;是指在企业专职从事安全生产管理工作的人员&#xff0c;包括企业安全生产管理机构的负责人及其工作人员和施工现场专职安全生产管理人员。武汉安全员…

Firewall App Blocker v1.7 防火墙管理设置工具多语言版

Firewall App Blocker 是一款由 BlueLife 与 Velociraptor 开发的免费且功能强大的防火墙设置软件。在 Windows 操作系统中,您可以使用 Windows 防火墙来阻止或解除阻止某些应用程序的联网,然而微软并没有为 Windows 防火墙提供一个易于使用的界面,来让用户使用其强大的功能…

高斯分布、高斯混合模型、EM算法详细介绍及其原理详解

相关文章 K近邻算法和KD树详细介绍及其原理详解朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解决策树算法和CART决策树算法详细介绍及其原理详解线性回归算法和逻辑斯谛回归算法详细介绍及其原理详解硬间隔支持向量机算法、软间隔支持向量机算法、非线性支持向量机算法详细…

【备战面试】每日10道面试题打卡-Day5

本篇总结的是计算机网络知识相关的面试题&#xff0c;后续也会更新其他相关内容 文章目录1、计算机网络的各层协议及作用是什么&#xff1f;2、简述一下DNS的工作流程3、TCP与UDP有什么区别&#xff1f;4、TCP协议如何保证可靠传输5、拥塞控制机制是什么&#xff1f;6、HTTP 与…

朋友去华为面试,轻松拿到26K的Offer,羡慕了......

最近有朋友去华为面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

应用层与传输层~

文章目录应用层自定义应用层协议什么是自定义应用层协议自定义方式运输层运输层概述运输层特点运输层协议UDP协议UDP的特点UDP首部格式校验规则TCP协议TCP的特点TCP协议段格式TCP的性质确认序号超时重传连接管理三次握手四次挥手TCP的状态滑动窗口流量控制拥塞控制延迟应答捎带…

linux笔记(10):ubuntu环境下,基于SDL2运行lvgl+ffmpeg播放mp4

文章目录1.ubuntu安装ffmpeg1.1 源码安装1.1 克隆ffmpeg源码1.2 配置编译条件&#xff0c;编译&#xff0c;安装1.2 直接安装依赖包2.下载lvgl源码2.1 测试原始代码2.2 运行lv_example_ffmpeg_2()例程2.2.1 配置 LV_USE_FFMPEG 为 12.2.2 lv_example_ffmpeg_2()替换lv_demo_wid…

C++核心知识(二)—— 类和对象(类的封装)、对象的构造和析构(浅拷贝、深拷贝、explicit、动态分配内存)

【上一篇】C核心知识&#xff08;一&#xff09;—— C概述、C对C的扩展(作用域、struct类型、引用、内联函数、函数默认参数、函数占位参数、函数重载)【下一篇】C核心知识&#xff08;三&#xff09;—— 静态成员(变量、函数、const成员)、面向对象模型(this指针、常函数、常…

linux安装pycharm

linux安装pycharm1.下载相关软件包2. 安装步骤2.1 解压文件2.2 开启命令2.4 创建快捷方式官网链接 https://www.jetbrains.com/pycharm/download/#sectionlinux 1.下载相关软件包 找到自己下载的版本下载 2. 安装步骤 2.1 解压文件 进入压缩包路径 解压文件【我指定了解…

设计模式-第10章(建造者模式)

建造者模式建造者模式建造者模式解析建造者模式的基本代码结构建造者模式 建造者模式&#xff08;Builder&#xff09;&#xff0c;将一个复杂对象的构建和表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 如果我们用了建造者模式&#xff0c;那么用户就只需指定…

欢乐消除开心假日协议解密

欢乐消除开心假日协议解密协/议/流/量/解/密分析欢乐消除开心假日这款游戏流量的协议加密方式。序欢乐消除开心假日是一款合成模拟家装的游戏&#xff0c;在这个游戏中&#xff0c;你将成为一位充满热情的设计师&#xff0c;与好友一起经营工作室。你需要根据客户的需求重新设计…

详解PyTorch Tensor 数据类型——张量

目录 张量 张量的结构 张量的创建 张量的操作 数学运算 逻辑运算 形状操作 索引和切片 张量的维度变换 常见的数据类型存储 附录PyTorch官方API中文文档 张量 在PyTorch中&#xff0c;张量&#xff08;Tensor&#xff09;是一种常见的数据类型&#xff0c;它是一个…

如何快速将多图片合并拼接成一张大图并保留原图质量 - 极速图片合成拼接器软件简介

在工作中我们有时需要把多张图片打印在一张纸上&#xff0c;那就必须手动排列和调整每张图片的大小&#xff0c;这可是一项费时费力的任务。 借助极速图片合成拼接器这款软件&#xff0c;终于可以快速自动解决这种任务啦&#xff01; 它是一款可以自动一次性将多个图像文件合并…

Jenkins部署angular11自动打包

可能年纪大了&#xff0c;对于新东西的学习和接收有点慢&#xff0c;花了差不多一周的时间&#xff0c;终于把jenkins配置好了&#xff0c;可以自动打包&#xff0c;与手动打出来的一样&#xff0c;以后就解放双手了。#!/bin/bashnpm cache clean -fnpm -vnode -vnpm install n…

ubuntu 18.04.06LST安装R4.0+版本报错及解决过程

1. sudo apt-get update无法正常使用 错误:13 http://ppa.launchpad.net/webupd8team/sublime-text-3/ubuntu bionic Release 404 Not Found [IP: 2620:2d:4000:1::3e 80] 解决措施&#xff1a;删除 webupd8team/sublime-text-3这个ppa文件。 sudo add-apt-repository --…

MySQL调优 - SQL查询深度分页问题

一、问题引入 例如当前存在一张表test_user&#xff0c;然后往这个表里面插入3百万的数据&#xff1a; CREATE TABLE test_user (id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键id,user_id varchar(36) NOT NULL COMMENT 用户id,user_name varchar(30) NOT NULL COMMENT 用…

嵌入式学习笔记——寄存器开发STM32 GPIO口

寄存器开发STM32GPIO口前言认识GPIOGPIO是什么GPIO有什么用GPIO怎么用STM32上GPIO的命名以及数量GPIO口的框图&#xff08;重点&#xff09;输入框图解析三种输入模式GPIO输入时内部器件及其作用1.保护二极管2.上下拉电阻&#xff08;可配置&#xff09;3.施密特触发器4.输入数…