SpringBoot核心机制解读一、总体了解

一、SpringBoot的基础使用

SpringBoot框架非常庞大,功能也非常多,基本上成了现在J2EE开发方向的事实标准。以SpringBoot扩展出来的生态圈基本上涵盖了所有的技术方向。对于SpringBoot,可以轻易的查出上百种使用方式,但是SpringBoot到底是什么样的?哪些功能是Spring的,哪些是SpringBoot的?要怎么全面深度的去学习以及把握SpringBoot框架呢?很多时候其实都是很模糊的。
这一系列文字只是为了记载学习SpringBoot框架底层的一些学习笔记。有些是自己写的,有些是网上收集的。会更多关注底层,而关于SpringBoot的使用,会有简单介绍,但不是重点。你只需要搭建一个简单的SpringBoot项目,就能把整个过程跟踪下来。

二、SpringBoot底层整体理解

SpringBoot框架的整体功能其实都浓缩在spring.factories文件当中。
我们创建SpringBoot工程后,会引入一个mave依赖:org.springframework.boot:spring-boot-starter:2.4.5。这个依赖就是SpringBoot的基础依赖。 在对应的spring-boot-2.4.5.jar这个包中,就会包含有spring.factories配置文件。SpringBoot框架就是围绕这个配置文件来展开他的所有功能实现的。

这里采用目前最新的稳定版本2.4.5来测试

在这里插入图片描述

打开文件内容,这其实就是一个key-value形式的配置文件,大致是这样一个结构

# Logging Systems
org.springframework.boot.logging.LoggingSystemFactory=...
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=...
# ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=...
# ConfigData Loaders
org.springframework.boot.context.config.ConfigDataLoader=...
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=...
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=...
# Application Listeners
org.springframework.context.ApplicationListener=...
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=...
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=...
# Failure Analysis Reporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=...

那现在我们就要来理解下这个配置文件:
首先:这个配置文件中每一个配置就对应了SpringBoot中提供的一种功能机制。
这个配置文件,从形式上看,就能很容易的理解为一种类似于JAVA的SPI扩展机制的配置文件。每个key对应一个功能接口,后面的value对应这个接口的多个实现。但是这里的功能实现,并不是全指java中的接口实现类,而是与这个功能相关的核心实现类,这个在后面的细节讲解中会体会到。
很多功能从接口名字上也能有个大致的理解。例如org.springframework.context.ApplicationListener 对应SpringBoot的事件监听功能。org.springframework.context.ApplicationContextInitializer对应SpringBoot的框架启动初始化功能。针对每个功能,他们的加载以及工作的流程机制是不一样的,但是正是这些机制构成了SpringBoot框架的整体。我们想要整体把握SpringBoot框架,就需要从这些功能入手。
然后:这个配置文件是可以扩展的。
在SpringBoot的基础maven依赖org.springframework.boot:spring-boot-starter:2.4.5下,还包含了另外一个基础的依赖org.springframework.boot:spring-boot-autoconfigure:2.4.5。这个依赖对应的jar包下同样有一个spring.factories文件。大概结构是这样:

# Initializers
org.springframework.context.ApplicationContextInitializer=...
# Application Listeners
org.springframework.context.ApplicationListener=...
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=...
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=...
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=...
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=...
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=...

他在spring-boot-starter的spring.factories文件基础上,又增加了一些配置。正是这些配置一起实现了SpringBoot的自动装配。也就是说,SpringBoot会扫描ClassPath下的所有META/spring.factories文件,整合到一起形成项目的基础功能配置,然后以这些配置信息为基础,实现出不同的功能。

当然,SpringBoot在上层扩展实现的过程当中,也还出现了非常多扩展机制,以至于基于spring.factories文件的扩展方式在实际开发过程中其实用得非常少了。但是,其实这才是SpringBoot框架的真正核心。
另外,从这里看出,SpringBoot框架内部其实有很多组件就是通过这个机制扩展出来的。那既然这种扩展机制,在框架内部可以用,那我们在使用SpringBoot框架时,同样也是可以用的。

三、SpringBoot的SPI加载机制

后面的部分也就会按照这个配置文件功能逐一进行梳理。在开始之前,肯定还是要了解下SpringBoot是如何来加载这些配置的。上面提到的整个spring.factories文件的加载过程,都在 org.springframework.core.io.support.SpringFactoriesLoader 这个类当中,所属jar包:spring-core-5.3.6.jar。查看下他的loadSpringFactories方法。

		private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
		Map<String, List<String>> result = cache.get(classLoader);
		if (result != null) {
			return result;
		}

		result = new HashMap<>();
		try {
			Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
			while (urls.hasMoreElements()) {
				URL url = urls.nextElement();
				UrlResource resource = new UrlResource(url);
				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
				for (Map.Entry<?, ?> entry : properties.entrySet()) {
					String factoryTypeName = ((String) entry.getKey()).trim();
					String[] factoryImplementationNames =
							StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
					for (String factoryImplementationName : factoryImplementationNames) {
						result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
								.add(factoryImplementationName.trim());
					}
				}
			}

			// Replace all lists with unmodifiable lists containing unique elements
			result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
					.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
			cache.put(classLoader, result);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load factories from location [" +
					FACTORIES_RESOURCE_LOCATION + "]", ex);
		}
		return result;
	}

在这个类下,还可以按照接口和classloader来查找具体的实现类。但是最为核心的就是这个方法。是整个SpringBoot读取配置信息的基础。

然后在一个只包含了简单的spirngBoot的web依赖(Maven依赖 org.springframework.boot:spring-boot-starter-web)的项目中启动,并在这个方法的return result一行加个断点,可以看到SpringBoot默认加载到的spring.factories配置有16个。
在这里插入图片描述

2.2.3版本还只有13个,到2.4.5版本增加到了16个。

这16个配置就对应了SpringBoot的16个核心功能点。在这每个功能点后不断的叠加实现类,就最终完成了Spring到SpringBoot的蜕变。而这16个功能点,也就是后面要梳理的重点。后面争取将这每一个功能点都梳理一遍,相信通过这样的梳理,就能够将SpringBoot使用过程中各种莫名其妙的“秘籍”有个整体的把握。

网上找了很多文章,很多功能点都有,但是非常零散。对于SpringBoot的说明也大都是集中在任何使用,很少有说明这些功能点的核心实现机制的。这里权当收集总结,加上自己的一些理解把。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

roykingw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值