Spring Boot2 源码 run > refreshContext > invokeBeanFactoryPostProcessors方法 (六)

老生谈spring(十五):invokeBeanFactoryPostProcessors 资深小白谈spring(十五):invokeBeanFactoryPostProcessors 1、上一节给大家展示了BeanFactoryPostProcessor的作用,现在给大家讲解它是如何生效的。前面几节已经带大家清楚地看到,开启了注解模式以后就会扫描指定包的所有含Component注解的class。所以只要加了Component的class都会被扫描器扫描到,扫描完了以后就会进入refresh的invokeBeanFactoryPostProcessors方法: 2、invokeBeanFacto 阅读详情

11.5 调用BeanFactoryPostProcessor各个实现类的方法

先说明两个类的关系
1.BeanFactoryPostProcessor:用来修改Spring容器中已经存在的bean的定义,使用ConfigurableListableBeanFactory对bean进行处理
2.BeanDefinitionRegistryPostProcessor:继承BeanFactoryPostProcessor,作用跟BeanFactoryPostProcessor一样,只不过是使用BeanDefinitionRegistry对bean进行处理
3.先处理BeanDefinitionRegistryPostProcessor类,然后在处理BeanFactoryPostProcessor类

BeanDefinitionRegistryPostProcessor处理过程

1.实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行
2.实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行
3.没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行
4.执行是指postProcessBeanDefinitionRegistry

BeanFactoryPostProcessor处理过程

1.实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行
2.实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行
3.没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行
4.执行是指postProcessBeanFactory

源码比较长

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();
	}

优先级最高的是ConfigurationClassPostProcessor,有兴趣的可以关注一下,import ComponentScan PropertySource 都是此类加载的

由于源码太长了,导致文章长度太长,我只截部分源码了,哪里有问题自己源码查看 版本 2.1.3.RELEASE

ConfigurationClassParser并不注册bean定义,主要是发现或者说放到对应的 Map中,后面调用者会根据不同得map注册bean定义,ConfigurationClassParser 并不是会将所有的类发现,同样 componentScanParser解析发现 @Component注解
 

ConfigurationClassParser parse()方法
跟据Bean定义的不同类型走不同的分支,但是最终都会调用到parse方法

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
				if (bd instanceof AnnotatedBeanDefinition) {
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}

		this.deferredImportSelectorHandler.process();
	}

 

doProcessConfigurationClass循环+递归发现

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		
		// 从当前配置类configClass开始向上沿着类继承结构逐层执行doProcessConfigurationClass,
	    // 直到遇到的父类是由Java提供的类结束循环
		SourceClass sourceClass = asSourceClass(configClass);
		do {
                // 循环处理配置类configClass直到sourceClass变为null
		// doProcessConfigurationClass的返回值是其参数configClass的父类,
		// 如果该父类是由Java提供的类或者已经处理过,返回null
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);
                //需要被处理的配置类configClass已经被分析处理,将它记录到已处理配置类记录
		this.configurationClasses.put(configClass, configClass);
	}

一个配置类的成员类(配置类内嵌套定义的类)也可能适配类,先遍历这些成员配置类,调用processConfigurationClass处理它们;
处理配置类上的注解@PropertySources,@PropertySource
处理配置类上的注解@ComponentScans,@ComponentScan
处理配置类上的注解@Import
处理配置类上的注解@ImportResource
处理配置类中每个带有@Bean注解的方法
处理配置类所实现接口的缺省方法
检查父类是否需要处理,如果父类需要处理返回父类,否则返回null 

 

/**
 * Apply processing and build a complete ConfigurationClass by reading the
 * annotations, members and methods from the source class. This method can be called
 * multiple times as relevant sources are discovered.
 * @param configClass the configuration class being build
 * @param sourceClass a source class
 * @return the superclass, or null if none found or previously processed
 */
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
		throws IOException {

	// Recursively process any member (nested) classes first,首先递归处理嵌套类
	processMemberClasses(configClass, sourceClass);

	// Process any @PropertySource annotations,处理每个@PropertySource注解
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), PropertySources.class,
			org.springframework.context.annotation.PropertySource.class)) {
		if (this.environment instanceof ConfigurableEnvironment) {
			processPropertySource(propertySource);
		}
		else {
			logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
					"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}

	// 这里是根据启动类 @ComponentScan 注解来扫描项目中的bean
	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
	if (!componentScans.isEmpty() &&
			!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
		for (AnnotationAttributes componentScan : componentScans) {
			// ①该配置类上注解了@ComponentScan,现在执行扫描,获取其中的Bean定义
			// 通过componentScanParser获取scannedBeanDefinitions的值 
            //会将你的项目的所有类包含@Component或者间接包含的类注入到容器中
			Set<BeanDefinitionHolder> scannedBeanDefinitions =
					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
			// 对Component scan得到的Bean定义做检查,看看里面是否有需要处理的配置类,
			// 有的话对其做分析处理
            //遍历我们项目中的bean,如果是注解定义的bean,则进一步解析
			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                //判断是否是注解bean
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(
						holder.getBeanDefinition(), this.metadataReaderFactory)) {
					// 如果该Bean定义是一个配置类,它进行分析
					parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}

	//递归解析处理每个@Import注解	
	// 注意这里调用到了getImports()方法,它会搜集sourceClass上所有的@Import注解的value值,
	// 具体搜集的方式是访问sourceClass直接注解的@Import以及递归访问它的注解中隐含的所有的@Import	
	processImports(configClass, sourceClass, getImports(sourceClass), true);

	// Process any @ImportResource annotations,处理每个@ImportResource注解
	if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		String[] resources = importResource.getStringArray("locations");
		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
		for (String resource : resources) {
			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
			configClass.addImportedResource(resolvedResource, readerClass);
		}
	}

	// Process individual @Bean methods,处理配置类中每个带有@Bean注解的方法
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}

	// Process default methods on interfaces,处理接口上的缺省方法
	processInterfaces(configClass, sourceClass);

	// Process superclass, if any
	// 如果父类superclass存在,并且不是`java`包中的类,并且尚未处理处理,
	// 则才返回它以便外层循环继续
	if (sourceClass.getMetadata().hasSuperClass()) {
		String superclass = sourceClass.getMetadata().getSuperClassName();
		if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
			this.knownSuperclasses.put(superclass, configClass);
			// Superclass found, return its annotation metadata and recurse
			return sourceClass.getSuperClass();
		}
	}

	// No superclass -> processing is complete,没找到需要处理的父类,处理结果
	return null;// 用返回null告诉外层循环结束
}

说下this.componentScanParser 这个是重点,为什么加个@Component注解就会加入到容器中,全部是这的作用,会加载你所有@Component注解或者是间接注解的类都会加入到容器中 扫描到就会加入到容器

                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

                scanner.doScan(StringUtils.toStringArray(basePackages))

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
                //candidates 会包含你所有的类
                //basePackages 默认是启动类的包路径 我的启动类是在com.bjsdzk.api包下
                //他会搜索(classpath*:com/bjsdzk/api/**/*.class)路径下的
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

 

ESD放电模式以及电源箝位 (power clamp )电路 由于ESD电压具有很快的上升速度(其ESD脉冲上升时间约在10ns左右),Vrc端的电压因为RC延迟效应无法跟得上VDD端的ESD电压上升速度,Vrc端的为低电位导致反相器工由于ESD电压具有很快的上升速度(其ESD脉冲上升时间约在10ns左右),Vrc端的电压因为RC延迟效应无法跟得上VDD端的ESD电压上升速度,Vrc端的为低电位导致反相器工作将输出端Vout电压上拉到高电位。从而Vg端的高电位触发导通了NMOS元件(Mesd)的晶体管,因而ESD电流便经由Mesd而泄放掉。由于晶体管Mesd的栅极导通 阅读详情

相关推荐

SAC安装与相关库文件(.so)的安装

摘要 SAC: Seismic Analysis Code 是用于地震信号处理的一套软件。 本文将介绍SAC的安装,以及安装时遇到的一些问题。主要是一些动态库(lib**.so)找不到的问题。 本文的环境 64位的 Ubuntu 16.04 64位的系统是安装出现问题的主要原因 1. SAC获取与安装 SAC 的安装,只需要解压,然后修改环境变量即可!!!不需要任何编译!!! 1.1. SAC 获取与解压 SAC软件获取地址:http://ds.iris.edu/ds/nodes/dmc/forms/s.

WangCY的博客 4335

你知道Spring中BeanFactoryPostProcessors是如何执行的吗?

了解了BeanDefinition以及生命周期的大概概念之后,我们班可以试着看一下源码!我们上一章也说到,BeanFactoryPostProcessors的执行时机是:在扫描完成之后,实例化之前! 那么我们看一下Spring是如何去回调BeanFactoryPostProcessors的呢? org.springframework.context.support.AbstractApplicationContext#refresh org.springframework.context.support.A

皇甫嗷嗷叫 765

Keil MDK编译错误#541解决方案与ARM_Compiler包解析

在嵌入式开发中,编译器工具链的依赖管理是确保项目顺利构建的关键环节。以Keil MDK为例,其软件包依赖机制通过组件化设计实现功能解耦,其中ARM_Compiler包专门处理系统IO重定向等编译器扩展功能。这种架构既提升了模块复用性,也带来了版本兼容性挑战。当出现'Error #541: component missing'报错时,通常是由于中间件组件(如文件系统)在新版本中显式依赖了ARM_Compiler包。开发者需要通过Pack Installer安装该包,并在Run-Time Environment

weixin_32129187的博客 368

springboot2.x 源码笔记-Bean的定义BeanDefinition invokeBeanFactoryPostProcessors

springboot的源码(spring)主要分为几个部分 本人博客原地址:springboot2.x 源码笔记-Bean的定义BeanDefinition invokeBeanFactoryPostProcessors 创作时间: 2019.06.05 11:18 1、构造SpringApplication,完成spring.factories文件中Initializers与Listeners的加载 2、加载配置文件,通过ConfigFileApplicationListener 3、加载BeanDef

qq_22351805的博客 392

快手极速版抓包实战:安卓/iOS双端获取client_salt全流程解析(避坑指南)

本文详细解析了在安卓和iOS平台上获取快手极速版关键参数`client_salt`的全流程,包括环境配置、抓包工具使用、参数识别与转换等实战技巧。特别针对双端差异和反抓包机制提供了避坑指南,帮助开发者高效安全地完成数据获取任务。

weixin_29021195的博客 714

E28 LoRa模块透传 定点传输 RSSI测试与MicroPython应用

测试说明 测试模块数:3 测试模式:配置模式和传输模式 如果没有检测到串口,首先检查是否安装串口驱动CH341SER,下载链接,提取码:vaw2 工作模式 模式(0-3) M2 M1 M0 模式介绍 备注 0 传输模式 1 0 0 串口打开,无线打开,连续透明传输 空速支持手动配置和自适应波特率自动调节;连续模式双方波特率必须一致 1 RSSI 1 0 1 串口打开,无线打开,RSSI功能打开 模块每100ms输出RSSI强度值 2 测距模式 1 1 0 保留 - 3 配置模式

GniLAY1022的博客 4243

invokeBeanFactoryPostProcessors

简介 调用bean工厂的后置处理器 解析 初始化三个集合 //第一步:首先调用BeanDefinitionRegistryPostProcessor的后置处理器 Set<String> processedBeans = new HashSet<>(); //保存BeanFactoryPostProcessor类型的后置 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(

linの编程之路 853

基于matlab版本的三维直流电法反演算法

可以使用RESINVM3D工具包等现成的MATLAB工具进行三维直流电法反演。反演问题求解:基于MATLAB的反演问题求解算法实现和应用,包括反演问题数值模拟、反演问题参数优化和反演问题结果分析。希望这个代码示例能帮助你入门三维直流电法反演。如果有更具体的需求或问题,可以进一步探讨。反演过程中可能需要调整正则化参数和优化算法的设置。需要根据实际问题实现,可能涉及复杂的数值计算。

ytttr873的博客 668

spring的核心方法只之invokeBeanFactoryPostProcessors

ps:在这一步所执行的扩展类可以是spring自带的扩展类或是程序员往程序中加入的,平时主要是执行spring自带的扩展类比如。这里说的程序员手动加入是指,在执行spring容器的refresh方法之前就,通过调用容器的接口,手动的往容器中加入。:通过注解的方式往spring容器中加入的。:通过注解的方式往spring容器中加入的。:手动的往spring容器中加入的。执行了通过手动方式加入到容器中的。接口的实现类的做法,代码如下。执行程序员手动加入到容器中的。的父类方法就是指的扩展类中的。

weixin_41249051的博客 745

2023年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题4)-网络部分解析-附详细代码

2023年全国职业院校技能大赛网络系统管理赛项模块A:网络构建(样题4)-网络部分解析-附详细代码

bfq05234214的博客 441

AI 测试工程师 — 6 个月学习计划表

AI 转型测试工程师 —— 6 个月学习计划表

weixin_46453070的博客 1068

【SpringBoot】一张图看懂初始化阶段-refreshContext

springboot的启动分为两部分,一部分是注解,一部分是SpringApplication.run(Springboot.class, args),那么我们的注解又是如何嵌入到程序中呢?进入ConfigurationClassParser这个类后,方法调用也是挺绕的,这里就不深究了…到这里,就可以看到一系列bean的操作,继续跟踪进入invokeBeanFactoryPostProcessors(调用在上下文中注册为bean的工厂处理器)方法。

精益求精 654

摇骰子、抽奖转盘酒桌游戏 人生重启模拟器小程序源码分享-开通流量主躺着赚钱

摇骰子、抽奖转盘酒桌游戏 人生重启模拟器小程序源码分享-开通流量主躺着赚钱

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1650

Spring boot启动原理及相关组件

ConfigurationClassPostProcessor的优先级为最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。在github里,我把Spring Boot应用启动的拓展组件(自定义的应用初始器、监听器、事件、ApplicationRunner)都写了例子,可参照阅读。

2611_94915296的博客 417

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

简单聊聊 SpringBoot 框架执行源码

一条主线构造收集 SPI → 准备环境(加载配置) → 创建空容器 → 填充上下文 → refresh(解析配置类 + 条件装配 + 启动 Tomcat + 实例化单例) → 发布就绪事件 → 执行 Runner。三个扩展点(refresh 前改容器)、(监听启动全生命周期事件)、(就绪后执行一次性逻辑)。面试时先画事件时间线 + refresh 12 步,再把"自动装配在哪步、Tomcat 在哪步"钉到具体步骤上,基本就聊透了。

weixin_47626220的博客 489

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

SpringBoot2.7.3自动配置过程源码分析

在启动SpringBoot时首先会创建SpringBootApplication对象,在创建这个对象的过程中会去读取各个starter下spring.factories文件中的自动配置信息,为后续准备自动配置做准备。然后调用对象的run方法在run方法中,会创建上下文对象(AnnotationConfigServletWebServerApplicationContext),在创建上下文对象时,会先注册一些BFPP信息,其中包括ConfigurationClassPostProcessor。

weixin_63653446的博客 302

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

上一篇: Spring Boot2 源码 run refreshContext 方法 (七)
下一篇: shell 导入、导入 mongoDB脚本
三笠爷
博客等级 码龄9年 18粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值