首页 > 其他分享 >【SpringBoot】SpringBoot自动装配原理

【SpringBoot】SpringBoot自动装配原理

时间:2024-07-06 15:27:47浏览次数:22  
标签:装配 SpringBoot beanFactory currentRegistryProcessors ppName registry new 原理 class

在上一篇文章中,讲述了 SpringBoot核心启动流程源码解析 其中,主要是构造方法和run方法的处理,本篇接着准备上下文环境后续,讲述是如何将springboot是如何完成自动装配,主线其实就是

  • 什么时候完成 对主类的加载,也即对SpringBootApplication类加载到IOC容器中
  • 什么时候完成对SpringBootApplication上注解的递归解析
  • 什么时候完成 @Import(AutoConfigurationImportSelector.class) 的默认配置类的加载处理。

启动类注册到IOC容器中

	// 可以看到主类是一个class 
	if (source instanceof Class<?>) {
		return load((Class<?>) source);
	}

	// 递归解析是否包含compoent注解,这里是有的
	if (isComponent(source)) { // 是否包含compoent注解
		// 注册SpringBootApp类到ioc 容器中
		this.annotatedReader.register(source);
		return 1;
	}

	@Configuration
	public @interface SpringBootConfiguration {
	}

	// 注册bean
	public void registerBean(Class<?> beanClass) {
		doRegisterBean(beanClass, null, null, null, null);
	}
	// 将主类Class包装成一个BeanDefinitionHolder 进一步保证成 definitionHolder
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

	// 获取beanName
	String beanName = definitionHolder.getBeanName();
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

	// 深入进去可以看到 添加到IOC中两个重要的Map中,
	this.beanDefinitionMap.put(beanName, beanDefinition);
	this.beanDefinitionNames.add(beanName);

在这里插入图片描述
这里就完成了将SpringBootApp主类,注册到IOC的两个重要的Map中。等待后续的实例化,以及解析对应类上的注解上。

重要的类

在构成方法中,添加了7个初始化类。

  setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

会遍历执行其中的方法,其中两个类给BFPP中添加了两个类 CachingMetadataReaderFactoryPostProcessor、ConfigurationWarningsPostProcessor。正在容器刷新的时候,会执行对应的方法进行解析主类上的注解。

	protected void applyInitializers(ConfigurableApplicationContext context) {
		// 遍历
		for (ApplicationContextInitializer initializer : getInitializers()) {
			Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
					ApplicationContextInitializer.class);
			Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
			initializer.initialize(context);
		}
	}

SharedMetadataReaderFactoryContextInitializer

	public void initialize(ConfigurableApplicationContext applicationContext) {
		// 给IOC里加入BFPP 刷新的时候会进行处理 CachingMetadataReaderFactoryPostProcessor 类
		applicationContext.addBeanFactoryPostProcessor(new CachingMetadataReaderFactoryPostProcessor());
	}

ConfigurationWarningsApplicationContextInitializer

	public void initialize(ConfigurableApplicationContext context) {
		// 加入对象
		context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));
	}

invokeBeanFactoryPostProcessors

	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);
		}

SharedMetadataReaderFactoryContextInitializer
注册一个类,internalCachingMetadataReaderFactory

		@Override
		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
			register(registry);
			configureConfigurationClassPostProcessor(registry);
		}

		private void register(BeanDefinitionRegistry registry) {
			BeanDefinition definition = BeanDefinitionBuilder
					.genericBeanDefinition(SharedMetadataReaderFactoryBean.class, SharedMetadataReaderFactoryBean::new)
					.getBeanDefinition();
			registry.registerBeanDefinition(BEAN_NAME, definition);
		}
		
		// 添加 internalConfigurationAnnotationProcessor
		private void configureConfigurationClassPostProcessor(BeanDefinitionRegistry registry) {
			try {
				BeanDefinition definition = registry
						.getBeanDefinition(AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME);
				definition.getPropertyValues().add("metadataReaderFactory", new RuntimeBeanReference(BEAN_NAME));
			}
			catch (NoSuchBeanDefinitionException ex) {
			}
		}

在这里插入图片描述

	invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

	// 遍历bfpp进行处理
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

解析主类上的注解信息

		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			parser.parse(candidates);

		// 递归解析
		SourceClass sourceClass = asSourceClass(configClass, filter);
		do {
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		
		// 核心流程
		this.deferredImportSelectorHandler.process();
		handler.processGroupImports();

		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

在这里插入图片描述
好了,核心流程,就是这样,其实就是用spring提供的BPFF拓展流程进行加载解析默认配置类。后续就开始bean容器的生成操作。

流程图

在这里插入图片描述

标签:装配,SpringBoot,beanFactory,currentRegistryProcessors,ppName,registry,new,原理,class
From: https://blog.csdn.net/jia970426/article/details/140224210

相关文章

  • SpringBoot如何集成和使用开源工作流引擎camunda
    使用camunda开源工作流引擎有:通过docker运行、使用springboot集成、部署camunda发行包、基于源代码编译运行等多种方式。其中,通过源代码编译运行的方式最为复杂,具体参考:https://lowcode.blog.csdn.net/article/details/136206057文本重点介绍如何在SpringBoot应用程序中如何集......
  • 【C/C++ new/delete和malloc/free的异同及原理】
    new/delete和malloc/free都是用于在C++(以及C语言在malloc/free的情况下)中动态申请和释放内存的机制,但它们之间存在一些显著的异同点。以下是对这两组函数/运算符的异同点的详细分析:相同点目的相同:两者都用于在堆(heap)上动态地分配和释放内存。手动管理:无论是new/delete还是......
  • 计算机组成原理复习与预习指南~持续更新~
    计算机组成原理是计算机科学领域的基石,理解它不仅能帮助你更好地掌握计算机的工作原理,还能为你在编程、系统设计和性能优化方面提供强大的理论支持。本文将带你深入探索计算机的组成,从CPU、存储器到系统总线和I/O系统,全面解析各个部分的工作原理和实际应用。同时,我们也会结......
  • 基于SpringBoot+vue的车辆充电桩系统(带1w+文档)
    基于SpringBoot+vue的车辆充电桩系统(带1w+文档)本次设计任务是要设计一个车辆充电桩管理系统,通过这个系统能够满足车辆充电桩管理系统的管理功能。系统的主要功能包括首页、个人中心、维修员管理、用户管理、电桩类别管理、充电桩管理、充电桩报修管理、维修回复管理、系......
  • 基于java+springboot+vue实现的图书商城管理系统(文末源码+Lw)283
     摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本图书商城管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理......
  • 基于java+springboot+vue实现的旅游推荐系统(文末源码+Lw)280
    摘 要传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装旅游推荐系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,旅游推荐系统的有效......
  • 基于java+springboot+vue实现的流浪动物管理系统(文末源码+Lw)277
     摘    要在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对流浪动物信息管理的提升,也为了对流浪动物信息进行更好的维护,流浪动物管理系统的出现就变得水到渠成......
  • 基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
    摘   要传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的药店管理系统。本药店......
  • 基于java+springboot+vue实现的药店管理系统(文末源码+Lw)285
    摘   要传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,药品信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的药店管理系统。本药店......
  • 数据库原理之并发控制的基本概念
    我们今天继续来看数据库原理,我们简单讲讲数据库的并发控制。并发控制的定义并发控制是为了保证事务的隔离性和一致性,数据库管理系统需要对并发操作进行正确调度。并发控制的主要技术有:、时间戳、乐观控制法、多版本并发控制等。并发操作带来的数据不一致性主要有以下三点:......