Spring Boot 概述与原理
本文最后更新于:2024年9月8日 晚上
Spring Boot 概述与原理
Spring Boot概述
Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速,敏捷地开发新一代基于 Spring 框架的应用程序,也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。
Spring Boot 以约定大于配置的核心思想 ,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置,同时它集成了大量常用的第三方库配置(例如 Redis,MongoDB,Jpa,RabbitMQ,Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。
优点
为所有Spring开发者更快的入门。
开箱即用,提供各种默认配置来简化项目配置。
内嵌式容器简化Web项目。
没有冗余代码生成和XML配置的要求。
运行原理探究
pom.xml
父依赖
其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件。
1 2 3 4 5 6 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.2.5.RELEASE</version > <relativePath /> </parent >
1 2 3 4 5 6 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-dependencies</artifactId > <version > 2.2.5.RELEASE</version > <relativePath > ../../spring-boot-dependencies</relativePath > </parent >
这里才是真正管理Spring Boot应用里面所有依赖版本的地方,Spring Boot的版本控制中心。
注意 :导入依赖默认是不需要写版本,但是如果导入的包没有在依赖中管理着就需要手动配置版本了。
启动器 spring-boot-starter
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency >
springboot-boot-starter-xxx :就是spring-boot的场景启动器。
spring-boot-starter-web :帮我们导入了web模块正常运行所依赖的组件。
Spring Boot将所有的功能场景都抽取出来,做成一个个的starter(启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来,要用什么功能就导入什么样的场景启动器即可,也可以自己自定义 starter
主启动类
1 2 3 4 5 6 7 8 @SpringBootApplication public class SpringBootApplication { public static void main (String[] args) { SpringApplication.run(SpringBootApplication.class, args); } }
@SpringBootApplication
作用 :注自动初始化Spring 容器,扫描并实例化Bean并自动配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { }
@SpringBootConfiguration
作用 :Spring Boot项目的配置注解,Spring Boot Configuration注解可以用Java代码的形式实现Spring中xml配置文件的配置效果。
1 2 3 4 @Configuration public @interface SpringBootConfiguration { }
这里的@Configuration
,说明这是一个配置类,配置类就是对应Spring的xml 配置文件。
@EnableAutoConfiguration
作用 :开启Spring Boot功能,这样自动配置才能生效。
1 2 3 4 5 6 @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { }
@AutoConfigurationPackage
:自动配置包。
1 2 3 @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
@import
:Spring底层注解@import
,给容器中导入一个组件。
Registrar.class
:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器。
@Import({AutoConfigurationImportSelector.class})
:给容器导入组件。
AutoConfigurationImportSelector
:自动配置导入选择器,那么它会导入哪些组件的选择器呢?这个类中有一个这样的方法。
1 2 3 4 5 6 7 8 protected List<String> getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this .getSpringFactoriesLoaderFactoryClass(), this .getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct." ); return configurations; }
这个方法又调用了SpringFactoriesLoader
类的静态方法,进入SpringFactoriesLoader类loadFactoryNames()
方法。
1 2 3 4 5 public static List<String> loadFactoryNames (Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
继续查看 loadSpringFactories
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null ) { return result; } else { try { Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories" ) : ClassLoader.getSystemResources("META-INF/spring.factories" ); LinkedMultiValueMap result = new LinkedMultiValueMap(); while (urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while (var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for (int var11 = 0 ; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]" , var13); } } }
@ComponentScan
作用 :自动扫描并加载符合条件的组件或者bean,将这个bean定义加载到IoC容器中。
1 2 3 4 5 6 7 8 @ComponentScan("com.example") public class SpringBootApplication { public static void main (String[] args) { SpringApplication.run(SpringBootApplication.class, args); } }
SpringApplication
这个类主要做了以下四件事情 :
推断应用的类型是普通的项目还是Web项目。
查找并加载所有可用初始化器,设置到initializers属性中。
找出所有的应用程序监听器,设置到listeners属性中。
推断并设置main方法的定义类,找到运行的主类。
查看构造器:
1 2 3 4 5 6 7 public SpringApplication (ResourceLoader resourceLoader, Class... primarySources) { this .webApplicationType = WebApplicationType.deduceFromClasspath(); this .setInitializers(this .getSpringFactoriesInstances(); this .setListeners(this .getSpringFactoriesInstances(ApplicationListener.class)); this .mainApplicationClass = this .deduceMainApplicationClass(); }
spring.factories
Spring Boot包下的META-INF/spring.factories
,中有很多自动配置的文件,这就是自动配置根源所在,例如:
WebMvcAutoConfiguration
可以看到这些都是JavaConfig配置类,而且都注入了一些Bean
所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories
配置文件,并将其中对应的org.springframework.boot.autoconfigure
包下的配置项,通过反射实例化为对应标注了@Configuration
的JavaConfig
形式的IoC容器配置类,然后将这些都汇总成为一个实例并加载到IoC容器中。
结论
Spring Boot在启动的时候从类路径下的META-INF/spring.factories
中获取EnableAutoConfiguration
指定的值。
将这些值作为自动配置类导入容器,自动配置类就生效,帮我们进行自动配置工作。
整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure
的jar包中。
它会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件。
有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。
run方法流程分析