Spring Boot使用与启动原理

it2022-05-05  127

目录

目标

what

构建系统

方式1:继承starter parent

方式2:通过spring-boot-dependencies

打包为可执行的jar

通过源码看原理

启动流程图

主要类

EmbeddedWebApplicationContext

AnnotationConfigEmbeddedWebApplicationContext

BeanPostProcessor

SpringApplication

configurationProperties

可执行Jar(fat jar)

why

how

spring boot可执行jar的目录结构

如何从标准jar或嵌套jar中加载内容

 如何启动jar

启动流程


目标

讲述通过源码了解的springboot启动原理与扩展点,并以输出流程图。

what

对spring框架和第三方jar包进行分组,依赖AutoConfiguration特性,快速搭建Spring应用。

构建系统

方式1:继承starter parent

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.BUILD-SNAPSHOT</version> </parent>

方式2:通过spring-boot-dependencies

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.0.0.BUILD-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

Main入口类

//直接使用run方法,其他配置交给properties文件吧。 @SpringBootApplication public class Application{ public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

 

打包为可执行的jar

需要添加spring-boot-maven-plugin

<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>

mvn package

 

通过源码看原理

启动流程图

主要类

EmbeddedWebApplicationContext

作为WebApplicationContext,通过内部的EmbeddedServletContainerFactory bean进行自行引导。

通过EmbeddedServletContainerFactory进行EmbeddedServletContainer的创建、初始化、运行。

EmbeddedServletContainerFactory支持Spring IOC、生命周期回调、属性占位符变量等。

嵌入servlet容器将自动注册Filter和Servlet 只有一个servlet,将mapping '/';任何命名为dispatcherServlet的Servlet,将mapping '/'; 多个servlet,则小写bean name将作为mapping前缀; 任何Filer将mapping '/*'。

AnnotationConfigEmbeddedWebApplicationContext

对如下注解类进行注册

使用@Configuration的类使用@Component的类符合JSR-330的依赖注入javax.inject

覆盖规则

多个@Configuration类型,加载顺序靠后的@Bean将覆盖顺序靠前的@Bean,可用于外部Configuration Bean覆盖内部Configuration Bean

ConfigFileApplicationListener

org.springframework.boot.context.config.ConfigFileApplicationListener

作为org.springframework.boot.env.EnvironmentPostProcessor的实现类,处理ApplicationEnvironmentPreparedEvent事件

驱动使用springFactoriesLoader去实例化EnvironmentPostProcessor的其他实现,如完成加载本地配置文件,确定activeProfile, application[-profile].properties/yml  

 

BeanFactoryPostProcessor 

 在BeanFactory实例初始化完成后,执行该扩展,例如覆盖或添加property/bean。

BeanPostProcessor

bean生命周期接口

beanFactory的钩子,允许对新建bean实例进行自定义修改

SpringApplication

从java main方法开启,引导和启动一个Spring应用。

configurationProperties

作用

通过前缀,批量匹配与使用外部配置属性。

注意

field必须有getter setter方法因为未继承@Component注解,需要与@Component相关注解(@Service @Component @Configuration)一起使用,以便被视为bean。 @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ConfigurationProperties {}

 

与@Value对比

简洁 前缀+fieldName路径,批量匹配外部配置; @Value必须在类中列举key并使用 ${}占位符类型识别 支持类型识别,@Value 所有val类型识别为String

 

可执行Jar(fat jar)

why

java本身不支持加载嵌套jar,即jar中包含jar。

how

spring boot可执行jar的目录结构

+-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-BOOT-INF +-classes //应用程序的class | +-mycompany | +-project | +-YourClasses.class +-lib //应用依赖的jar +-dependency1.jar +-dependency2.jar

如何从标准jar或嵌套jar中加载内容

org.springframework.boot.loader.jar.JarFile

如何定位资源

使用最外层jar的物理文件偏移量表示每个资源(如应用程序class\嵌套jar中的class等)的位置。

来自spring官网

如何加载资源

仅需要定位到外层jar的合适部分,不需要解压也不需要将jar全部读入到内存,然后交由springboot自定义的classloader去做。

 如何启动jar

org.springframework.boot.loader.Launcher

特殊的引导程序,作为可执行jar的main-class入口,工作流程概述为创建合适的urlclassloader、加载资源、调用应用程序的main()

子类

JarLauncher 加载嵌套jar的资源,BOOT_INF/libWarLauncher 加载嵌套war的资源,WEB_INF/lib,WEB-INF/lib-provided/PropertiesLauncher

META-INF/MANIFEST.MF

Main-Class 指定具体的launcher Start-Class 指定应用程序的main()所在类 例如 Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.xx.xx.MyApplication

启动流程

bootstrapClassLoader加载jre创建系统类加载器,由系统类加载器加载JarLauncher,反射并执行jarLauncher的main();launcher创建LaunchedURLClassLoader并指定资源为所有嵌套jar的uri;将LaunchedURLClassLoader设置为Thread contextClassLoader,用其加载Start-Class,反射获取main方法并执行。SpringApplication.run()流程

启动的应用程序只能使用Thread contextClassLoader进行加载,使用systemClassLoader加载嵌套jar将会失败。

 

 

 


最新回复(0)