`
shinesuo
  • 浏览: 156146 次
  • 性别: Icon_minigender_1
  • 来自: 宇宙
社区版块
存档分类
最新评论

Spring Boot 源码分析 —— SpringApplication

 
阅读更多

1. 概述

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // <1>
public class MVCApplication {

public static void main(String[] args) {
SpringApplication.run(MVCApplication.class, args); // <2>
}

}
  • <1> 处,使用 @SpringBootApplication 注解,标明是 Spring Boot 应用。通过它,可以开启自动配置的功能。
  • <2> 处,调用 SpringApplication#run(Class<?>... primarySources) 方法,启动 Spring Boot 应用。

上述的代码,是我们使用 Spring Boot 时,最最最常用的代码。而本文,我们先来分析 Spring Boot 应用的启动过程

关于 @SpringApplication 注解,我们会后面单独开文章,详细解析。

2. SpringApplication

org.springframework.boot.SpringApplication ,Spring 应用启动器。正如其代码上所添加的注释,它来提供启动 Spring 应用的功能。

Class that can be used to bootstrap and launch a Spring application from a Java main method.

大多数情况下,我们都是使用它提供的静态方法:

// SpringApplication.java

public static void main(String[] args) throws Exception {
SpringApplication.run(new Class<?>[0], args);
}

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 创建 SpringApplication 对象,并执行运行。
return new SpringApplication(primarySources).run(args);
}
  • 前两个静态方法,最终调用的是第 3 个静态方法。而第 3 个静态方法,实现的逻辑就是:
    • 首先,创建一个 SpringApplication 对象。详细的解析,见 「2.1 构造方法」 
    • 然后,调用 SpringApplication#run(Class<?> primarySource, String... args) 方法,运行 Spring 应用。详细解析,见 「2.2 run」 

2.1 构造方法

// SpringApplication.java

/**
* 资源加载器
*/
private ResourceLoader resourceLoader;
/**
* 主要的 Java Config 类的数组
*/
private Set<Class<?>> primarySources;
/**
* Web 应用类型
*/
private WebApplicationType webApplicationType;

/**
* ApplicationContextInitializer 数组
*/
private List<ApplicationContextInitializer<?>> initializers;
/**
* ApplicationListener 数组
*/
private List<ApplicationListener<?>> listeners;

public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 初始化 initializers 属性
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化 listeners 属性
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
  • SpringApplication 的变量比较多,我们先只看构造方法提到的几个。
  • resourceLoader 属性,资源加载器。可以暂时不理解,感兴趣的胖友,可以看看 《【死磕 Spring】—— IoC 之 Spring 统一资源加载策略》 文章。
  • primarySources 属性,主要的 Java Config 类的数组。在文初提供的示例,就是 MVCApplication 类。
  • webApplicationType 属性,调用 WebApplicationType#deduceFromClasspath() 方法,通过 classpath ,判断 Web 应用类型。
    • 具体的原理是,是否存在指定的类,艿艿已经在 WebApplicationType 上的方法添加了注释,直接瞅一眼就明白了。
    • 这个属性,在下面的 #createApplicationContext() 方法,将根据它的值(类型),创建不同类型的 ApplicationContext 对象,即 Spring 容器的类型不同。
  • initializers 属性,ApplicationContextInitializer 数组。
    • 通过 #getSpringFactoriesInstances(Class<T> type) 方法,进行获得 ApplicationContextInitializer 类型的对象数组,详细的解析,见 「2.1.1 getSpringFactoriesInstances」 方法。
    • 假设只在 Spring MVC 的环境下,initializers 属性的结果如下图:`initializers` 属性
  • listeners 属性,ApplicationListener 数组。
    • 也是通过 #getSpringFactoriesInstances(Class<T> type) 方法,进行获得 ApplicationListener 类型的对象数组。
    • 假设只在 Spring MVC 的环境下,listeners 属性的结果如下图:`listeners` 属性
  • mainApplicationClass 属性,调用 #deduceMainApplicationClass() 方法,获得是调用了哪个 #main(String[] args) 方法,代码如下:

    // SpringApplication.java

    private Class<?> deduceMainApplicationClass() {
    try {
    // 获得当前 StackTraceElement 数组
    StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
    // 判断哪个执行了 main 方法
    for (StackTraceElement stackTraceElement : stackTrace) {
    if ("main".equals(stackTraceElement.getMethodName())) {
    return Class.forName(stackTraceElement.getClassName());
    }
    }
    } catch (ClassNotFoundException ex) {
    // Swallow and continue
    }
    return null;
    }
    • 在文初的例子中,就是 MVCApplication 类。
    • 这个 mainApplicationClass 属性,没有什么逻辑上的用途,主要就是用来打印下日志,说明是通过这个类启动 Spring 应用的。

2.1.1 getSpringFactoriesInstances

#getSpringFactoriesInstances(Class<T> type) 方法,获得指定类类对应的对象们。代码如下:

// SpringApplication.java

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// <1> 加载指定类型对应的,在 `META-INF/spring.factories` 里的类名的数组
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// <2> 创建对象们
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
// <3> 排序对象们
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

相关推荐

    SpringBoot 源码解析 —— SpringApplication 源码分析.docx

    Spring Boot@SpringBootApplication 源码分析 本文对 Spring Boot 中的@SpringBootApplication 源码进行了深入分析。通过分析@SpringBootApplication 注解和 SpringApplication 类的 run 方法,我们可以了解 Spring...

    spring boot整合JPA——demo

    本示例“spring boot整合JPA——demo”将演示如何在Spring Boot项目中配置和使用JPA。 首先,我们需要理解Spring Boot与JPA的关系。Spring Boot是基于Spring框架的快速开发工具,它通过自动化配置减少了常规设置...

    Spring Boot课件1 —— 创建和运行Spring Boot项目

    **Spring Boot创建与运行项目详解** Spring Boot是Java开发领域中的一个热门框架,它通过简化配置和自动装配,使得创建和运行Spring应用变得更加容易。在本篇内容中,我们将深入探讨如何利用Spring Boot来创建和...

    spring boot源码分析

    深入学习spring boot 懂得各个标签,注解的用途和原理

    果子学院Spring boot源码解析

    《果子学院Spring Boot源码解析》是一套深入学习Spring Boot源码的教程,旨在帮助开发者深入了解这个流行的Java开发框架的内部工作机制。Spring Boot简化了Java应用的初始搭建以及开发过程,它集成了大量常用的第三...

    Spring Boot源码(spring-boot-2.6.2.zip)

    在这个版本中,我们将深入探讨Spring Boot的核心特性、工作原理以及如何通过源码来理解其内部机制。 首先,Spring Boot的核心理念是“约定优于配置”,它通过预设许多默认配置,减少了开发者需要手动配置的繁琐工作...

    spring-boot源码

    3. **Spring Application**:Spring Boot应用通过`SpringApplication`类启动。它负责初始化Spring的ApplicationContext,并加载`src/main/resources/application.properties`或`application.yml`中的配置。`run()`...

    第三节-springboot源码解析-王炸篇.pdf

    通过源码分析,开发者可以更好地理解Spring Boot的自动装配、启动流程以及如何自定义启动器。Spring Boot的自动装配原理涉及到Spring Boot的核心特性,它简化了基于Spring的应用开发,通过自动配置减少了大量的配置...

    Spring Boot实战派(源码)

    《Spring Boot实战派》源码提供了丰富的学习材料,旨在帮助开发者深入理解并...通过分析《Spring Boot实战派》源码,读者不仅可以了解上述技术点,还能学习到如何在实际项目中应用这些技术,提升开发效率和代码质量。

    基于spring boot餐厅管理系统源码.zip

    基于spring boot餐厅管理系统源码 基于spring boot餐厅管理系统源码 基于spring boot餐厅管理系统源码 基于spring boot餐厅管理系统源码 基于spring boot餐厅管理系统源码 基于spring boot餐厅管理系统源码 ...

    java maven工程 spring boot 学习源码

    本学习资源包“java maven工程 spring boot 学习源码”提供了一个可以直接运行的示例工程,有助于深入理解Spring Boot和Maven的结合使用。 首先,我们需要了解Spring Boot的核心特性。Spring Boot通过内嵌的Servlet...

    java毕业设计——基于spring boot的音乐播放网站设计与实现(源码+数据库).zip

    java毕业设计——基于spring boot的音乐播放网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的音乐播放网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的音乐播放网站设计与...

    基于 Spring Boot + MySQL 开发的博客系统源码.zip

    基于 Spring Boot + MySQL 开发的博客系统源码 基于 Spring Boot + MySQL 开发的博客系统源码 基于 Spring Boot + MySQL 开发的博客系统源码 基于 Spring Boot + MySQL 开发的博客系统源码 基于 Spring ...

    spring boot 深入浅出源码

    在深入理解Spring Boot的源码时,我们首先要明白其核心设计理念——“约定优于配置”。Spring Boot通过预设默认配置,使得开发者能够快速启动并运行应用,同时提供了丰富的启动器(Starters)来简化依赖管理。 ...

    Spring Boot源码(spring-boot-2.6.2.tar.gz)

    Spring Boot是Java开发领域的一款非常流行的框架,它简化了基于Spring的应用程序开发流程。Spring Boot 2.6.2是该框架...通过分析源码,我们可以学习到Spring框架的最佳实践,以及如何设计和实现一个健壮的微服务架构。

    spring-boot-2.7.0.zip源码

    通过深入阅读和分析Spring Boot 2.7.0的源码,我们可以了解到Spring Boot是如何实现其核心特性的,以及如何利用Spring Framework进行扩展和定制。同时,这也有助于我们更好地利用Spring Boot进行微服务开发,提高...

    《Vue Spring Boot前后端分离开发实战》源码Vue+Spring Boot前后端分离开发实战教学课件(PPT)

    这本《Vue Spring Boot前后端分离开发实战》的源码提供了深入学习和实践这一技术栈的机会。以下是对其中涉及知识点的详细说明: 1. **Vue.js**:Vue.js是一个轻量级的前端JavaScript框架,以其易学易用、组件化和...

    Spring5 源码分析(第 2 版) .zip

    《Spring5 源码分析(第 2 版)》是针对Spring框架第五个主要版本的深度解析著作,由知名讲师倾心打造,旨在帮助读者深入理解Spring框架的内部工作机制,提升对Java企业级应用开发的专业技能。本书涵盖了Spring框架的...

    Spring Boot 2.2.2 启动过程源码分析.md

    Spring Boot 2.2.2 启动过程源码分析,SpringApplication 实例 run 方法运行过程,.分析了 SpringApplication 实例对象构造方法初始化过程,下面继续来看下这个 SpringApplication 对象的 run 方法的源码和运行流程。

    使用Gradle 构建spring Boot工程系列项目源码(配合第五篇文章)

    本资源包"使用Gradle构建Spring Boot工程系列项目源码"是针对一系列教程的配套源代码,旨在帮助开发者深入理解如何利用Gradle有效地构建Spring Boot应用程序。通过分析这些源码,我们可以学习到以下关键知识点: 1....

Global site tag (gtag.js) - Google Analytics