详解SpringBoot底层原理实现

网站建设5年前发布
30 0 0

​笔者记得差不多在2015年以前,要部署一个Web应用,那得准备各种Web容器,比如Tomcat,然后打war包,然后部署到Web容器的特定目录下,以此来完成一个应用的部署,而且应用中的web.xml配置文件是必不可少的。可是近几年使用了SpringBoot后,发现写一个Web应用真的太简单了,一个SpringBootApplication注解直接搞定,什么web.xml啥都不用了,干净利索。,对于SpringBoot,我想99.99%的老铁都会使用,但是又有几人知道为什么加了这么一个简单的注解,一个Web应用就这么轻松的被创建出来了呢?今天笔者就来扒一扒它的神秘面纱。,先来说说SpringBoot的几大核心能力,包括:自动装配、内置Web容器以及整合SpringMVC,因此笔者本篇主要从上述三个维度来详细阐述它的底层原理。,先通过一张图来说明下SpringBoot启动的整体流程:,20230306153012e5009e2341c4712b123555f46f32cccee9a240645,我们研究任何源码,首先得找到它的入口,SpringBoot的入口毫无疑问是SpringApplication.run方法,找到了入口,然后顺藤摸瓜看看SpringBoot是如何实现上述的三大核心能力的。,那么,什么是自动装配?笔者看来自动装配就像是搭积木,将多种形状的模型组装在一起,对应SpringBoot中的自动装配则是将单独的第三方功能,组装到Spring这个大的容器中,让Spring可以全权管理所涉及到的Bean实例,并在整个项目中使用。,我们还是从入口入手。可以想下,SpringBoot肯定是需要使用到Spring的核心能力的,而Spring的核心能力就是如何管理Bean的生命周期,那就脱离不了Spring的应用上下文,但是我们在使用SpringBoot的过程中,从头到尾都没有明确创建过Spring应用上下文。于是我们有理由相信,一定是在SpringApplication的run方法中创建了这个Spring的应用上下文,而事实上的确如此:,2023030615272852ff8408364011da3cf50322fbefbf98a965d9269,2023030615301325ff37303853f80a630610abbfde7563f80005158,上述代码中,创建了AnnotationConfigServletWebServerApplicationContext,该类是SpringBoot实现的应用上下文,它是GenericApplicationContext的子类:,2023030615272962d804c71e0c9306fb649729d084be8e541a12742,很明显,它具有Spring应用上下文的一切能力。在创建出了Spring应用上下文后,接下来就是去扫描需要被Spring管理的类,得到BeanDefinition信息,然后完成Bean的生命周期管理。,咱们顺着SpringBootApplication注解,可以发现在EnableAutoConfiguration注解上有Import({AutoConfigurationImportSelector.class}的注解信息,Spring会调用AutoConfigurationImportSelector的selectImports方法,将该方法返回的所有字符串对应的类,走Bean的生命周期流程并进行管理:,2023030615273045ece4d1531987a7b55691f313637416ccc168978,那么,这个方法返回的字符串数组就是自动装配的玄机所在,咱们看看它的具体代码实现就一目了然了:,20230306153013b635f277648157e0fe6021d9aecb88516c39f0801,20230306153140d915de693c7c4a18cc4423e6ac2dcba0b9c532641,2023030615273358521053283e49e018d3025a5dae1af9cc2e4b960,顺着getCandidateConfigurations方法看:调用loadSpringFactories方法,读取所有META-INF/spring.factories目录中的配置信息,返回配置信息中key为EnableAutoConfiguration类型的value值,然后筛选出非exclusions的值,就得到了将要被返回的所有字符串数组的数据。,很简单,Spring就是读取项目中所有的META-INF/spring.factories配置文件信息,然后加载EnableAutoConfiguration对应的value值。既然Spring已经加载了这些value值到上下文容器中,那就可以使用这些value对应的Bean做为桥梁,来加载更多的其他Bean。,如果老铁们自己实现了一些工具包,也想自动整合进来,也完全可以增加一个META-INF/spring.factories的配置文件作为桥梁来实现,so easy,有木有?,上述Spring已经加载到了EnableAutoConfiguration对应的value值,在SpringBoot自己提供的spring.factories文件中,默认支持了一堆的值,这些都是SpringBoot默认提供的自动装配类(也可以理解为桥梁类),其中有一个名为:ServletWebServerFactoryAutoConfiguration的配置类,这个配置类中导入了EmbeddedTomcat:,20230306152733f2ce6cb433fd04b597708803fa33928103e69d783,而EmbeddedTomcat这个类中又通过@Bean注解配置了TomcatServletWebServerFactory:,20230306152733810e92a02fca6149f09301a2112c60bc44002a696,这个类是用来创建Tomcat的工厂类,它是ServletWebServerFactory接口的实现类:,20230306153015846aa43601f59ee827f6010232b7d7eb40ab2e817,这表明在Spring应用上下文容器中已经存在了类型为ServletWebServerFactory的Bean,大家记住这个很重要,因为接下来在创建容器的时候就要用到这个Bean。,在上面我们说过,SpringBoot会创建一个AnnotationConfigServletWebServerApplicationContext的Spring应用上下文,Spring在执行应用上下文的refresh方法时,会执行onRefresh方法,来执行子上下文的逻辑:,2023030615301514e1f1a69bb76a92f6738761b0e6616b40712b410,而这个子上下文的onRefresh方法则是执行createWebServer方法创建Web服务,也就是咱们所说的Tomcat:,202303061527351918ba1415ad80e6fee451cd50265ef073ba8b230,2023030615273552bd07a965662ece7d37493b2061fcbf508bcc876,原来如此,这里在createWebServer方法中会从Spring的Bean工厂中获取到ServletWebServerFactory的实例,而这个实例不就是我们上面提到的TomcatServletWebServerFactory类型的实例吗?获取到这个ServletWebServerFactory实例后,调用它的getWebServer方法来创建一个Web服务:,20230306153016a5c627965463851b30d5866ee76aa2fa0455bb456,没错,就是直接创建一个Tomcat。呵呵,大功告成!,话说,在使用SpringBoot时,写一个Controller和在SpringMVC中的方法一模一样,那这个又是怎么做到的呢?,还是看SpringBoot自己提供的spring.factories文件,其中有一个名为DispatcherServletAutoConfiguration的自动配置类,这个类就是那个连接SpringBoot和SpringMVC的桥梁。,我们知道,SpringMVC里面一个核心类就是DispatcherServlet,所以我们完全可以大胆的猜想,在这个自动配置类,一定配置了DispatcherServlet,事实上也确实如此:,20230306153017982cc97052777e9fc00798a9824fb90e1f0b8c356,有了这个类,一切就水到渠成。,波哥,互联行业从业10余年,先后担任项目总监及架构师。目前专攻技术,喜欢研究技术原理。技术全面,主攻java,精通JVM底层机制及Spring全家桶底层框架原理,熟练掌握当前主流的中间件、服务网格等技术原理。,

© 版权声明

相关文章