IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 关于 SpringBoot 你知道多少 -> 正文阅读

[Java知识库]关于 SpringBoot 你知道多少

关于 SpringBoot 你知道多少


1、简介

? ?SpringBoot 从本质上看就是 Spring,它只是帮你做了 那些你 必须去做 又 很繁琐 的 Spring Bean 配置。Spring Boot 本身不提供 Spring 的核心功能,而是作为 Spring 的脚手架框架,使用 “约定优于配置” 的理念,达到 快速构建项目、预置三方配置、开箱即用 的目的。


补充:

? ?SpringBoot 两大策略:

  • 开箱即用(Out of box)

    ? ?指在开发过程中,通过在 Maven 项目的 pom 文件中添加 相关依赖包,然后使用 对应注解 来替代 繁琐的 xml 配置文件 以管理对象的生命周期。

  • 约定优于配置(Convention over configuration)

    ? ?是一种由 SpringBoot 本身来配置 目标结构,由 开发者 在结构中添加信息 的 软件设计范式。


? ?SpringBoot 的优点:

  • 可以创建 基于 Maven(或 Gradle)的、独立的 Spring 应用程序,生成 可执行的 Jar 包(或 War包)

  • 内嵌 Tomcat(或 Jetty)等 Servlet 容器

  • 提供 自动配置 的 “starter” 项目对象模型(Project Object Model,简称 POM,定义了 对其它库的 传递依赖)以简化 Maven 配置

  • 尽可能自动配置 Spring 容器

  • 提供 运行时的应用监控

  • 与 云计算 天然集成




2、SpringBoot 的启动流程

? ?SpringBoot 项目创建完成会默认生成一个名为 xxxApplication 的入口类,通过该类的 main 方法可以启动 SpringBoot 项目。

? ?在 main 方法中,通过 SpringApplication 的静态方法(run 方法)进行 SpringApplication 类的实例化操作,再调用 实例化对象 的 run 方法 来完成 整个项目的初始化和启动。
在这里插入图片描述


扩展:

? ?SpringApplication 实例化对象的 run() 源代码

public ConfigurableApplicationContext run(String... args) {
    	// 创建 Stopwatch 对象,记录 run 方法 的启动时长
        StopWatch stopWatch = new StopWatch();
    	// 开始计时
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    	// 配置 Headless 属性
        this.configureHeadlessProperty();
    	// 获得所有的监听器 (SpringApplicationRunListeners 数组)
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
    	// 启动所有的监听器
        listeners.starting();

        Collection exceptionReporters;
        try {
            // 创建 ApplicationArguments 对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 环境配置,加载所有的配置属性
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            // 打印 Banner
            Banner printedBanner = this.printBanner(environment);
            // 创建应用程序上下文容器
            context = this.createApplicationContext();
            // 获取异常报告器
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            // 准备容器,组件对象之间进行关联
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            // 初始化容器
            this.refreshContext(context);
            // 初始化操作之后执行,默认实现为空
            this.afterRefresh(context, applicationArguments);
            // 停止计时
            stopWatch.stop();
            // 打印启动日志
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            // 通知监听器:容器启动完毕
            listeners.started(context);
            // 调用 ApplicationRunner 和 CommandLineRunner 的运行方法
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            // 异常处理
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            // 通知监听器:容器正在运行
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            // 异常处理
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
	return context;
}



3、SpringBoot 的自动装配

3.1、SpringBoot 的自动装配:

? ?当我们使用 SpringBoot 时,只需要引入对应的 Starters 依赖,SpringBoot 启动时便会自动加载相关依赖,配置相应的初始化参数,以最快捷、简单的形式对 第三方软件 进行集成。


3.2、SpringBoot 的自动装配流程:

? ?SpringBoot 通过 @EnableAutoConfiguration 开启自动配置,加载 spring.factories 中注册的各种 AutoConfiguration 类,当某个 AutoConfiguration 类 满足器注解 @Conditional 指定的生效条件(Starters 提供的依赖、配置 或 Spring 容器中 是否存在某个 Bean 等)时,实例化该 AutoConfiguration 类 中定义的 Bean(组件等),并注入 Spring 容器,就可以完成 依赖框架的自动配置。

在这里插入图片描述



4、SpringBoot 的注解

注解说明
@SpringBootApplicationSpringBoot 的启动注解
@EnableAutoConfigurationSpringBoot 的自动配置注解
@ImportSpringBoot 的加载配置类注解
@ConditionalSpringBoot 的前置条件判断注解

补充:@Conditional 的衍生注解

注解说明
@ConditionalOnProperty在指定的属性有指定值的条件下
@ConditionalOnBean在容器中有指定 Bean 的条件下
@ConditionalOnMissingBean在容器中没有指定 Bean 的条件下
@ConditionalOnSingleCandidate当指定的 Bean 在容器中只有一个(或多个)但指定了primary(首选) Bean 的条件下
@ConditionalOnClass在 classpath(类路径)有指定类的条件下
@ConditionalOnMissingClass在 classpath(类路径)没有指定类的条件下
@ConditionalOnResource在 classpath(类路径)有指定资源的条件下
@ConditionalOnExpression在多个配置(表达式)满足 SpEL 表达式 的条件下
@ConditionalOnJava在运行环境符合指定 Java 版本的条件下
@ConditionalOnJndi在指定资源通过 JNDI 加载的条件下
@ConditionalOnCloudPlatform在运行环境符合指定 云平台 的条件下
@ConditionalOnWebApplication在项目是一个 Web 项目的条件下
@ConditionalOnNotWebApplication在项目不是一个 Web 项目的条件下



5、深入分析 SpringBoot 的自动装配

在这里插入图片描述


5.1、@SpringBootApplication

? ?SpringBoot 的自动装配机制由 @SpringBootApplication 集中体现,@SpringBootApplication 主要包含了以下的 3 个注解。

  • SpringBootConfiguration(本质是 @Configuration 配置类)
  • EnableAutoConfiguration(核心注解,负责启动 SpringBoot 的自动装配机制)
  • ComponentScan(启动 @Component 组件的扫描,扫描时 过滤掉 指定的类)

在这里插入图片描述


扩展:

? @SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan



5.2、@SpringBootConfiguration

? ?@SpringBootConfiguration 的作用是:标注这个类是一个 SpringBoot 的配置类,@SpringBootConfiguration 主要包括 @Configuration。


5.3、@EnableAutoConfiguration

? ?@EnableAutoConfiguration 是 SpringBoot 自动装配机制的核心注解,负责启动 SpringBoot 的自动装配机制,@EnableAutoConfiguration 主要包含以下 2 个注解。

  • @AutoConfigurationPackage(指定默认的包规则)
  • @Import(AutoConfigurationImportSelector.class)(自动配置的后续实现类)

在这里插入图片描述


5.3.1、@AutoConfigurationPackage

? ?@AutoConfigurationPackage 的作用是:将 添加该注解的类所在的 package 作为自动配置 package 进行管理,通过 @Import 将 package 注入到 IoC 容器中。

在这里插入图片描述


? 补充:

  • 实现 ImportBeanDefinitionRegistrar 接口 的类 可以将组件注册到 IoC 容器中

  • ImportBeanDefinitionRegistrar 接口 的实现方法为 registerBeanDefinitions()


AutoConfigurationPackages.Registrar:

? ?registerBeanDefinitions() 可以将 指定包中的所有组件 注册到容器中。

在这里插入图片描述

AutoConfigurationPackages.PackageImports:

在这里插入图片描述

? ?ClassUtils.getPackageName() 可以获取 标注 @AutoConfigurationPackage 注解的类的全限定名。

在这里插入图片描述


5.3.2、@Import(AutoConfigurationImportSelector.class)
  • @Import 加载 AutoConfigurationImportSelector 类
  • AutoConfigurationImportSelector 类 实现了 DeferredImportSelector 接口,DeferredImportSelector 接口 继承了 ImportSelector 接口
  • selectImports() 会去扫描 META_INF/Spring.factories 配置文件,并将其中的组件完成自动装配

在这里插入图片描述

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    // 1. 获取 @EnableAutoConfiguration 标注类的元信息
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    // 2. 获取自动装配类的候选类名集合
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    // 3. 移除重复对象
    configurations = removeDuplicates(configurations);
    // 4. 获取自动装配类的排除类名集合
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    // 5. 检查 候选类名集合 是否包括 排除类名集合
    checkExcludedClasses(configurations, exclusions);
    // 6. 移除 候选类名集合 中的 排除类名
    configurations.removeAll(exclusions);
    // 7. 进一步过滤 候选类名
    configurations = getConfigurationClassFilter().filter(configurations);
    // 8. 触发自动装配的导入事件
    fireAutoConfigurationImportEvents(configurations, exclusions);
    // 9. 返回自动装配的元信息
    return new AutoConfigurationEntry(configurations, exclusions);
}

5.3.2.1、获取自动装配类的候选类名集合

在这里插入图片描述

在这里插入图片描述

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 factoryTypeName = ((String)entry.getKey()).trim();
                    String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                    int var10 = var9.length;

                    for(int var11 = 0; var11 < var10; ++var11) {
                        String factoryImplementationName = var9[var11];
                        result.add(factoryTypeName, factoryImplementationName.trim());
                    }
                }
            }

            cache.put(classLoader, result);
            return result;
        } catch (IOException var13) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
        }
    }
}

while(urls.hasMoreElements()) 会执行三次循环:

  • 第一次循环:

在这里插入图片描述

  • 第二次循环

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 第三次循环

在这里插入图片描述


5.3.2.2、触发自动装配的导入事件
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
    // 1. 获取所有的自动装配事件监听器
   List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
   if (!listeners.isEmpty()) {
      AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
      for (AutoConfigurationImportListener listener : listeners) {
         invokeAwareMethods(listener);
          // 2. 执行自动装配事件
         listener.onAutoConfigurationImportEvent(event);
      }
   }
}

5.4、@ComponentScan

? ?@ComponentScan 的作用是:扫描 当前类所在的包 及其子包下 包含的注解,将 @Controller / @Service / @Component / @Repository 等注解 加载到 IoC 容器中。


5.5、总结

? ?SpringBoot 自动装配 的本质是:通过 Spring 去读取 META-INF/spring.factories 配置文件 并 根据配置文件中的 k-v 键值对(接口 全限定名 - 实现类 全限定名) 批量加载 bean 的过程。


? 补充:spring.factories
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:38:23  更:2022-07-20 18:38:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/31 7:18:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码