Springboot启动流程源码分析

Springboot启动流程源码分析(一)(自动配置)

我们首先从pom.xml文件开始分析

  • 其中它主要是依赖一个父项目,主要是管理控制项目的资源过滤及插件依赖!
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
  • 在父启动类里,发现还有一个父依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
  • 这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心;
    • 以后我们导入依赖默认是不需要写版本
    • 但是如果导入的包没有在依赖中管理着就需要手动配置版本了

启动器 spring-boot-starter介绍

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • springboot-boot-starter-xxx:就是spring-boot的场景启动器
  • spring-boot-starter-web:帮我们导入了web模块正常运行所依赖的组件
  • SpringBoot将所有的功能场景都抽取出来,做成一个个的starter (启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来
  • 我们要用什么功能就导入什么样的场景启动器即可 ;我们未来也可以自己自定义 starter;

主启动类SpringbootApplication---->一系列注解原理

1、SpringbootApplication主启动类main方法

  • 默认的主启动类,一个简单的启动类并不简单!下面我们来分析一下 @SpringBootApplication 注解都干了什么
@SpringBootApplication // 来标注一个主程序类 说明这是一个Spring Boot应用
public class SpringbootApplication {
public static void main(String[] args) {
//以为是启动了一个方法,没想到启动了一个服务
SpringApplication.run(SpringbootApplication.class, args);
}
}

2、@SpringBootApplication注解

  • 来标注一个主程序类 说明这是一个Spring Boot应用

  • SpringBoot就应该运行这个类的main方法来启动SpringBoot应用

  • 在这个注解中还有许多其他的注解,如下代码所示

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// ...
}

3、@ComponentScan注解(@SpringBootApplication子注解)

  • 该注解在Spring中很重要 ,它对应XML配置中的元素。

  • 作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中

4、@SpringBootConfiguration注解(@SpringBootApplication子注解)

  • 作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类
  • 在该注解下含有两个注解:@Configuration、@Component
@Configuration
public @interface SpringBootConfiguration {}
// @Configuration点进去得到下面的 @Component
@Component
public @interface Configuration {}
  • 这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件

  • 这里的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用!

我们回到 SpringBootApplication 注解中继续看。

5、@EnableAutoConfiguration(@SpringBootApplication的注解)

  • 注解作用:开启自动配置功能

    • 以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置
    • @EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效
  • 点进EnableAutoConfiguration注解继续查看:

    • @AutoConfigurationPackage :自动配置包

      @Import(AutoConfigurationPackages.Registrar.class)
      public @interface AutoConfigurationPackage {
      }
    • @import :Spring底层注解@import , 给容器中导入一个组件

      • Registrar.class 的作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器
  • 退到上一步,继续看@EnableAutoConfiguration的注解

  • **@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 **

    • AutoConfigurationImportSelector :自动配置导入选择器,那么它会导入哪些组件的选择器呢?我们点击去这个类看源码:
    • getCandidateConfigurations方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 这里的getSpringFactoriesLoaderFactoryClass()方法,返回的就是注解类Class:EnableAutoConfiguration
List<String> configurations = SpringFactoriesLoader.
loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
return configurations;
}
// 返回自动配置类EnableAutoConfiguration
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
  • 这个方法又调用了 SpringFactoriesLoader 类的静态方法loadFactoryNames() 方法
// @Nullable ClassLoader classLoader 参数为该类自己SpringFactoriesLoader
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
// 就是传过来的EnableAutoConfiguration.class;
String factoryTypeName = factoryType.getName();
// 这里又调用了loadSpringFactories方法,Map有键为EnableAutoConfiguration就返回,没有取空集合
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
  • 我们继续追踪查看 loadSpringFactories 方法
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
// 获得classLoader,我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
MultiValueMap<String, String> result = cache.get(classLoader);
// 缓存中若有,则直接返回
if (result != null) return result;
try {
// 去加载文件资源 "META-INF/spring.factories"
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// 将读取到的资源遍历,封装成为一个Properties
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
}

spring.factories文件

  • 我们可以全局搜索并打开spring.factories , 看到了很多自动配置的信息

AopAutoConfiguration实例

  • 随便找一个自动配置类打开看看,比如 :AopAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration{ }
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration{ }
  • 自动配置的实现是加载classpath下所有的META-INF/spring.factories配置文件
  • 将其中对应的 org.springframework.boot.autoconfigure 包下的配置项
  • 通过反射实例化将标注了 @ConfigurationJavaConfig形式的聚集加载到IOC容器完成配置
posted @   lam要努力  阅读(104)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示