springboot启动过程(1)-初始化

1   springboot启动时,只需要调用一个类前面加了@SpringBootApplication的main函数,执行SpringApplication.run(DemoApplication.class, args)即可,这里初始化了一个SpringApplication实例,然后调用run启动springboot。run方法中,调用了initialize,如下

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {

//把传入的source设置到SpringApplication的变量中 
  if (sources != null && sources.length > 0) {
    this.sources.addAll(Arrays.asList(sources));
  }

// 如果是web程序,设置web环境。web程序必须让类加载器存在servlet 和 ConfigurableWebApplicationContext
  this.webEnvironment = deduceWebEnvironment();

//找到ApplicationContextInitializer类实例化为成员变量,这个过程是找到所有的初始化器。
  setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  //把ApplicationListener实例化为变量,就是找到所有的事件监听器。

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

//找到入口类,即放置main函数的类。

  this.mainApplicationClass = deduceMainApplicationClass();
}

(1)初始化context。 上面setInitializers 得到了ApplicationContextInitializer类型对象的集合,ApplicationContextInitializer是一个可以用来初始化各种ApplicationContex的接口,就一个initialize方法,上面初始化的时候用到了getSpringFactoriesInstances方法如下,

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {
  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  // Use names and ensure unique to protect against duplicates
  Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);
  AnnotationAwareOrderComparator.sort(instances);
  return instances;
}

可以看到,方法用oadFactoryNames(type, classLoader));通过类型得到所有spring factories的名字,然后根据名字使用createSpringFactoriesInstances创造出实例对象,最后把创建好的对象排序并返回。springfactory是spring-boot-xxx(版本)包里面的META-INF/spring.factories如下 ,然后通过createSpringFactoriesInstances方法利用反射创造出这些实例,实例共四个都是ApplicationContextInitializer的实现类,作用也如下。

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\

//为ApplicationContext添加一个能够检查配置,在错误配置时能够打印报错信息的BeanFactoryPostProcessor
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\

//为ApplicationContext设置id
org.springframework.boot.context.ContextIdApplicationContextInitializer,\

//从ApplicationContext的环境配置中,读取Initializer并使用
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\

//为ApplicationContext设置一个环境变量,方便使用服务器正在监听的端口号。
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer

(2)初始化监听器   上文中setListeners进行监听器初始化操作,跟初始化context一样,根据类型ApplicationListener.class从spring.factories里找到各种监听器,applicationListener就一个方法onApplicationEvent,用于监听各种事件。

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener

* applicationContext 事件机制    spring的事件机制基于观察者模式,与所有的事件机制都基本类似,他们都需要 事件源, 事件 和事件监听器 组成。只是此处的事件源是ApplicationContext。包括两个重要部分,

ApplicationEvent: 容器事件,必须由 ApplicationContext发布。

    ApplicationListener: 监听器,可有容器中的任何监听器Bean担任。

我们使用时可以定一个event继承ApplicationEvent,然后定一个listener继承ApplicationListener,实现onApplicationEvent方法,在方法里可以根据事件类型判断事件,进行响应处理。事件发布的时候,需要得到ApplicationContext,调用publishEvent(event)进行发布即可。spring也内置了几个事件。

(3)上文的最后,deduceMainApplicationClass方法中,通过获取当前方法调用栈,得到main函数的类,赋值给成员变量。

  

时间: 2024-10-26 08:16:40

springboot启动过程(1)-初始化的相关文章

SpringBoot启动过程原理

最近这两年springboot突然火起来了,那么我们就来看看springboot的运行原理. 一.springboot的三种启动方式: 1.运行带有main方法的2.通过命令 Java -jar命令3.通过spring-boot-plugin的方式 二.springboot 启动时执行方法,有两种方式 第一种方式是用启动时的main方法加载静态方法. 另一种是用初始化注解@postconstruct 执行.(注意点必须void并且参数). 注意点:[1.@PostConstruct会先被执行,静

flex启动过程和初始化

如果不了解Flex发布的swf结构和初始化流程,会在工作中遇到困难,Flex发布的swf结构和Flex对显示层级的划分是Flex架构中的一部分. Flex发布的swf结构 Flex生成的swf是个2帧的MovieClip,文档类继承SystemManager,主时间轴上没有任何内容,帧上也没有代码,2帧结构是为创建加载应用程序的默认加载器,这种早期就开始使用的加载方式在如今仍然具有优势,默认的加载器如图: 加载器的外观是通过代码绘制的,SystemManager使用工厂模式来创建应用程序,这使得

Springboot 启动时Bean初始化,启动异常-Assert.isTrue(condition,message) 报错

Springboot 启动时Bean初始化启动异常Assert.isTrue(condition,message) 报错,如果 condition为false 则会出现 java.lang.IllegalArgumentException: message, org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'XXXXXX' defined in class path re

深入剖析Oracle启动过程内部初始化

1 Oracle启动选项; Oracle数据库在startup启动时,Oracle将在默认位置$ORACLE_HOME/dbs中查找初始化参数文件:Oracle以下面的顺序在其中寻找合适的初始化文件: Spfile$ORACLE_SID.ora Spfile.ora Init$ORACLE_SID.ora 可以用几种方式启动oracle数据库,不同方式启动将影响启动数据库的程度,启动状态由nomount(数据库未装载)-->mount(数据库完成装载)-->open(数据库打开) 1.1 ST

springboot启动过程(3)-refresh方法

1  springboot在启动的时候,会调用run方法,创建环境设置spring容器,其中包含refresh方法,完成配置类解析,各种beanFactoryPostProcess和beanPostProcessor注册,web内置容器构造,国际化配置初始化等,refresh调用了父类AbstractApplicationContext的refresh方法如下. public void refresh() throws BeansException, IllegalStateException

springboot启动过程(2)-run方法

1 springApplication的run run方法主要是用于创造spring容器ConfigurableApplicationContext对象. public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); // 构造一个任务执行观察器 stopWatch.start(); // 开始执行,记录开始时间 ConfigurableApplicationC

SpringBoot启动过程:

SpringApplication 的run()方法探秘 原文:https://juejin.im/post/5b8f05a5f265da43296c6102 原文地址:https://www.cnblogs.com/lyqf/p/11100364.html

springboot启动流程简析

Spring Boot可以轻松创建独立的,生产级的基于Spring的应用程序,而这只需要很少的一些Spring配置.本文将从SpringBoot的启动流程角度简要的分析SpringBoot启动过程中主要做了哪些事情. 说明: springboot 2.0.6.RELEASE SpringBoot启动简要流程图 附原始大图链接 启动流程概述 启动流程从角度来看,主要分两个步骤.第一个步骤是构造一个SpringApplication应用,第二个步骤是调用它的run方法,启动应用. 1 构造Sprin

源码分析SpringBoot启动

遇到一个问题,需要从yml文件中读取数据初始化到static的类中.搜索需要实现ApplicationRunner,并在其实现类中把值读出来再set进去.于是乎就想探究一下SpringBoot启动中都干了什么. 引子 就像引用中说的,用到了ApplicationRunner类给静态class赋yml中的值.代码先量一下,是这样: @Data @Component @EnableConfigurationProperties(MyApplicationRunner.class) @Configur