SpringBoot原理解析(超详细)

2023-11-05

SpringBoot原理解析

1.@SpringBootApplication原理解析

首先,我们直接追踪@SpringBootApplication的源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

这些注解虽然看起来很多,但是除去元注解,真正起作用的注解只有以下三个注解:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

1.1 @SpringBootConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

 可以看到,除去元注解,剩下的@Configuration注解,它的作用就是将当前类申明为配置类,同时还可以使用@bean注解将类以方法的形式实例化到spring容器,而方法名就是实例名,springboot靠这个注解去除了xml配置。

1.2 @ComponentScan

@ComponentScan作用就是扫描当前包以及子包,将有@Component@Controller@Service@Repository等注解的类注册到容器中,以便调用。

注:如果@ComponentScan不指定basePackages,那么默认扫描当前包以及其子包,而@SpringBootApplication里的@ComponentScan就是默认扫描,所以我们一般都是把springboot启动类放在最外层,以便扫描所有的类。

1.3@EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

@EnableAutoConfiguration是借助@Import的帮助导入AutoConfigurationImportSelector,将所有符合自动配置条件的bean定义加载到IoC容器

注:在AutoConfigurationImportSelector中使用SpringFactoriesLoader加载bean

 

 上图就是从SpringBoot的autoconfigure依赖包中的META-INF/spring.factories配置文件中摘录的一段内容,可以很好地说明问题。

从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

SpringBoot自动配置

 

starter机制

1.springboot的启动原理

创建一个SpringApplication对象,并调用了run方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = Collections.emptySet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        this.applicationStartup = ApplicationStartup.DEFAULT;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.bootstrapRegistryInitializers = this.getBootstrapRegistryInitializersFromSpringFactories();
        //获取所有初始化器    
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //获取所有监听器
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //定位main方法
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

1.1 获取初始化器
跟踪进入getSpringFactoriesInstances方法

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();
        //获取所有初始化器的名称集合
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        //根据名称集合实例化这些初始化器(通过反射)
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

从源码可以看出,该配置模块的主要使用到了SpringFactoriesLoader,即Spring工厂加载器,该对象提供了loadFactoryNames方法,SpringFactoriesLoader在META-INF/spring.factories配置文件里收集到文件中的类全名并返回一个类全名的数组,返回的类全名通过反射被实例化,就形成了具体的工厂实例,工厂实例来生成组件具体需要的bean。

1.2 获取初监听器

同样跟踪源码,发现其实监听器和初始化的操作是基本一样的,这里就不细说了

1.3定位main方法

跟踪源码进入deduceMainApplicationClass方法

    private Class<?> deduceMainApplicationClass() {
        try {
            //通过创建运行时异常的方式获取栈
            StackTraceElement[] stackTrace = (new RuntimeException()).getStackTrace();
            StackTraceElement[] var2 = stackTrace;
            int var3 = stackTrace.length;
            //遍历获取main方法所在的类并且返回
            for(int var4 = 0; var4 < var3; ++var4) {
                StackTraceElement stackTraceElement = var2[var4];
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        } catch (ClassNotFoundException var6) {
        }

        return null;
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot原理解析(超详细) 的相关文章

随机推荐

  • Qt的下载与安装说明(超全!)

    Qt的下载与安装说明 下载说明 一打开浏览器输入https www qt io 来到Qt的官网 点击Developers Get Started 下滑到这这里 点击here 选择我们的需要的版本点击 in the archive 这个网页打
  • ISBN码书籍信息查询

    小程序 有书乐享 第一版已正式上线 在做这个小程序的过程中 有个扫一扫功能 通过书籍的ISBN码扫描后进行书籍分享 而网上找到的方式 要不提供的接口很久 无法请求 要不就是收费 总之让人折腾 因此基于这种情况 基于现有的小程序实现功能提供接
  • 重磅报告

    过去5年 是中国互联网创新飞跃的五年 中国从具有先天人口优势的网络大国逐步迈向技术创新驱动的网络强国 我国互联网产业在5年里究竟发生了哪些变化 阿里研究院发布报告 创新飞跃的五年 10大关键词解读中国互联网 报告基于丰富的数据 以及鲜活的案
  • ArcGis10.2详细安装步骤

    目录 1 安装License Manager10 2 2 复制试用文件 3 安装ArcGis Desktop10 2中文版 4 更新本地许可 提供arcgis下载地址 暂时评论区留邮箱吧 下载之后会得到以下3个目录 按顺序进行操作或者安装
  • QT笔记- 队列信号槽绑定与自定义类型

    说明 使用Qt QueuedConnection队列绑定时 某些默认非队列绑定时可用的自定义类型此时会不可用 如自定义枚举类型 此错误Qt不会报错和提示 解决 在绑定前使用qRegisterMetaType
  • http、websocket、长连接、短连接(一)

    http websocket 长连接 短连接 一 http websocket 长连接 短连接 二 这一篇先讲一下http的长短连接的问题 1 HTTP协议与TCP IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接 HT
  • NetMonitor抓不到网卡

    在powershell 或Dos下输入命令 bcdedit set testsigning on 操作目的 打开系统的testSigning模式 使得非权威CA发放的签名可以使用
  • Type string trivially inferred from a string literal, remove type annotation (no-inferrable-types)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt TypeScript代码 private goY string www baidu com 会导致tslint报错 Type string trivially inferr
  • 华为OD机试 - 观看文艺汇演问题(Java)

    题目描述 为了庆祝中国共产党成立100周年 某公园将举行多场文艺表演 很多演出都是同时进行 一个人只能同时观看一场演出 且不能迟到早退 由于演出分布在不同的演出场地 所以连续观看的演出最少有15分钟的时间间隔 小明是一个狂热的文艺迷 想观看
  • 自动单选题批改程序C语言,标准单选题考试系统,又出问题了,求指教,怎么就串行了呢?...

    include include cls include toupper include time include malloctypedef struct char question 200 A 100 B 100 C 100 D 100
  • 拒绝后门程序-Alibabaprotect和AliPaladin

    详细参考帖子及评论区 流氓进程AlibabaProtect的删除 程序员吧 百度贴吧 首先打开服务找到AlibabaProtect 然后找到他的位置 C Program Files x86 AlibabaProtect 这个目录下有个uni
  • 巧解高并发之福利抽奖

    随着互联网的发展 高并发问题几乎是每个企业都会面临的问题 而目前解决高并发最受欢迎的便是微服务 通过类似于增加服务器数量而达到一种 人多力量大的 效果 但是 类似方法均需要技术及资本的支持 而当现有技术和资本不达标时 一切都是空谈 那么当技
  • mysql 数据多表join

    0 索引 JOIN语句的执行顺序 INNER LEFT RIGHT FULL JOIN的区别 ON和WHERE的区别 1 概述 一个完整的SQL语句中会被拆分成多个子句 子句的执行过程中会产生虚拟表 vt 但是结果只返回最后一张虚拟表 从这
  • 在cmd/bat脚本中获取当前脚本文件所在目录

    Q 在Win7 Win10中以管理员身份运行在cmd bat脚本时 如何获取当前脚本文件所在目录 当我们在Win7 Win10中使用鼠标右键的 以管理员身份运行 以管理员身份运行cmd bat脚本时 系统默认进入的目录是C Windows
  • 【Burp Suite】配置FireFox火狐浏览器burpsuite https抓包

    配置FireFox火狐浏览器burpsuite https抓包 配置火狐浏览器代理 Firefox配置证书 FireFox再配置代理 抓包 成功
  • centos7 安装mysql8.0

    1 官方文档 http dev mysql com doc mysql yum repo quick guide en 2 下载 Mysql yum包 http dev mysql com downloads repo yum 或者直接 w
  • VMware虚拟机安装+Ubuntu下载+VMware虚拟机配置运行

    一 安装虚拟机VMware 1 下载地址 下载 VMware Workstation Pro CN 2 进入官网 点击Window 16 Pro for Windows即可立即下载 3 下载好后 如图所示 4 运行exe文件 进入VMwar
  • Klipper seria.c 文件代码分析

    一 前言 Klipper 底层硬件的串口模块程序写的是否正确是决定下位机与上位机能否正常通信的前提 如果这个文件的驱动没写好 那上位机控制下位机就无从谈起 更无法通过上位机去验证下位机程序的正确性 本篇博文将详细解析 Klipper src
  • ORA-00933: SQL命令未正确结束 解决办法

    1 报错内容 Cause java sql SQLSyntaxErrorException ORA 00933 SQL 命令未正确结束 bad SQL grammar nested exception is java sql SQLSynt
  • SpringBoot原理解析(超详细)

    SpringBoot原理解析 1 SpringBootApplication原理解析 首先 我们直接追踪 SpringBootApplication的源码 Target ElementType TYPE Retention Retentio