0
点赞
收藏
分享

微信扫一扫

框架源码 – springboot启动过程


启动原理run

框架源码 – springboot启动过程_Web

springboot启动代码

@SpringBootApplication
public class AppApplication {
public static void main( String[] args ){
SpringApplication.run(AppApplication.class, args);
}
}

进入SpringApplication类的run()方法

//SpringApplication类的run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
//调用重写的方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
//由此可知启动类做了两个事情,一个是创建springapplication对象,再一个是执行run方法
return (new SpringApplication(primarySources)).run(args);
}

由以上代码可知启动类做了两个事情:一个是创建springapplication对象,再一个是执行run方法

创建SpringApplication对象

new SpringApplication(primarySources)

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

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 = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}

WebApplicationType.deduceFromClasspath();
  • 加载应用类型
  • NONE
  • 该应用程序不应作为Web应用程序运行,也不应启动嵌入式Web服务器
  • SERVLET
  • 默认springboot启动上下文类型就是servlet
  • REACTIVE
  • 该应用程序应作为反应式Web应用程序运行,并应启动嵌入式反应式Web服务器
this.getSpringFactoriesInstances(ApplicationContextInitializer.class)
  • 初始化spring factory
  • META-INF/spring.factories
this.getSpringFactoriesInstances(ApplicationListener.class)
  • 初始化监听器
  • META-INF/spring.factories
this.deduceMainApplicationClass()
  • 通过遍历 StackTrace 来查找到启动类

run()方法

run()方法源码

public ConfigurableApplicationContext run(String... args) { 
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();

Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
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);
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);
}
}

run()方法主要内容详解

  • StopWatch stopWatch = new StopWatch();
    stopWatch.start();
  • 开启计时器
  • this.configureHeadlessProperty();
  • 设置加载外设环境
  • SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();
  • 获取监听器
  • ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  • 初始化环境
  • java -jar test.jar --server.port=8888
  • 执行jar 参数server.port=8888
  • –server.port=8888
  • 初始化外部参数
  • this.prepareEnvironment(listeners, applicationArguments)
  • 加载准备环境
  • 把外部环境加到系统运行环境中
  • this.configureIgnoreBeanInfo(environment)
  • 配置忽略BeanInfo
  • Banner printedBanner = this.printBanner(environment);
  • 创建输出内容
  • 类型
  • OFF
  • CONSOLE
  • LOG
  • context = this.createApplicationContext();
  • SERVLET
  • org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
  • REACTIVE
  • org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
  • default
  • org.springframework.context.annotation.AnnotationConfigApplicationContext
  • this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
  • META-INF/spring.factories
  • this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
  • this.refreshContext(context);
  • this.prepareRefresh();
  • 初始化一些配置属性,验证配置文件
  • ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
  • 获取beanFactory
  • this.prepareBeanFactory(beanFactory);
  • 将context中的一些属性设置到beanFactory中
  • this.postProcessBeanFactory(beanFactory);
  • 注册Scope相关的类
  • this.invokeBeanFactoryPostProcessors(beanFactory);
  • 解析配置文件、生成所有的beanDefinitions
  • this.registerBeanPostProcessors(beanFactory);
  • 分类、排序、注册(注入)所有的BeanPostProcessors,用于处理 bean 的初始化流程
  • this.initMessageSource();
  • 多语言转化
  • this.initApplicationEventMulticaster();
  • 注册 applicationEventMulticaster
  • this.onRefresh();
  • 主要创建并初始化容器
  • this.registerListeners();
  • 事件注册监听者
  • this.finishBeanFactoryInitialization(beanFactory);
  • 主要是初始化非懒加载单例
  • this.finishRefresh();
  • 主要是开启Web容器
  • this.afterRefresh(context, applicationArguments);
  • (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
  • 开启日志
  • this.callRunners(context, applicationArguments);
  • 执行启动后加载
  • listeners.running(context);

介绍getSpringFactoriesInstances()方法

这个方法全文出现三次

  • 1.首先尝试从内存缓存中获取,如获取到就立即返回,没有则继续下面内容;
  • 2.从类加载路径(的jar文件)中获取全部的spring.factories文件路径;
  • 3.循环遍历读取这些文件中的键值对(K->List[V]);
  • 4.将读取内容放入内存缓存,下次再调用这个方法时会优先从缓存中获取;
  • 5.返回读取到的全部键值对集合(Map[K,List[V]]结构)。


举报

相关推荐

0 条评论