springboot启动流程,version:2.4.2
2021-01-19 22:32:33 0 举报
登录查看完整内容
springbootv2.4.2启动流程图
作者其他创作
大纲/内容
SystemEnvironmentPropertySourceEnvironmentPostProcessor将environment名称为systemEnvironment的source的类型由SystemEnvironmentPropertySource转换为OriginAwareSystemEnvironmentPropertySource
此时,environment的sources中有7个source,按顺序分别为configurationProperties、servletConfigInitParams、servletContextInitParams、systemProperties、systemEnvironment、random、OriginTrackedMapPropertySource
SpringFactoriesLoader.class.getClassLoader();判断classLoader是否为空,如果为空,则将使用的classLoader置为当前类的classLoader
AnnotationAwareOrderComparator.sort(instances)对工厂实例列表排序并返回
getSpringFactoriesInstances(ApplicationContextInitializer.class)
第四步
this.log = log; this.listeners = new ArrayList<>(listeners); this.applicationStartup = applicationStartup;SpringApplicationRunListeners成员变量初始化
this.resourceLoader = resourceLoader初始化类加载器,由于传入的resourceLoader为null,故初始化后,resourceLoader依然为null
判断事件类型是否为空,若为空则重新生成事件类型获取线程池,但取得的线程池为null
实例化ConfigTreeConfigDataLocationResolver
bindToSpringApplication(environment)将environment中以spring.main开头的source绑定到springApplication中注:springApplication有个environment属性,执行完此方法后它依然为null,应该是绑定了environment中的某些属性到SpringApplication中
若环境不为null,直接返回环境,否则通过不同的应用类型创建不同环境由于应用类型为SERVLET,故返回new StandardServletEnvironment()
ConfigurationPropertySources.attach(environment)使环境参数匹配环境,获取到environment中属性资源中的configurationProperties资源,将它置为空,再重新生成新的configurationProperties资源,并把environment的propertysourceList中放到它里边,propertysourceList里也包括了他自己,为什么要再次调用,暂不清楚
第一步
当事件为ApplicationEnvironmentPreparedEvent时
DefaultBootstrapContext bootstrapContext = createBootstrapContext()创建启动器上下文
由于this.addConversionService默认为true,故会获取到ApplicationConversionService的共享实例,即new ApplicationConversionService(),并将它们设置到应用环境中,属性执行类型转换时会使用它们ConversionService conversionService = ApplicationConversionService.getSharedInstance(); environment.setConversionService((ConfigurableConversionService) conversionService);
processAndApply()设置activeProfiles和defaultProfiles,并优先读取activeProfiles中的配置属性,
DelegatingApplicationListener不进行任何处理
this.listeners.forEach(listenerAction)listeners中的listener分别对启动上下文进行响应
stepName=\"spring.boot.application.starting\"listenerAction=(listener) -> listener.starting(bootstrapContext)stepAction=(step) -> { if (mainApplicationClass != null) { step.tag(\"mainApplicationClass\
LoggingApplicationListener识别到事件为ApplicationEnvironmentPreparedEvent,执行onApplicationEnvironmentPreparedEvent(event)方法,初始化loggingSystem
初始化resourceLoader,并且用resourceLoader生成SpringApplicationBannerPrinter实例bannerPrinter,判断bannerMode是LOG模式还是CONSOLE模式,决定用logger打印或是System.out打印,打印完成后返回生成的PrintedBanner实例
当事件为ApplicationStartingEvent时
RandomValuePropertySourceEnvironmentPostProcessor向environment的sources中加入了random的source,用以解析配置文件中的random.*
LoggingApplicationListener识别到事件为starting事件,执行onApplicationStartingEvent(event)方法初始化loggingSystem
ConfigDataEnvironmentPostProcessor对activeProfiles和defaultProfiles进行配置,扫描并读取配置文件中的配置属性等
该对象中维护了一个locations:\"classpath:/\"、\"classpath:/config/\"、\"file:./\"、\"file:./config/\"、\"file:./config/*/\",它们代表配置文件的扫描位置以及顺序(倒序,顺序是在processAndApply中反向遍历实现的)此对象还维护了一些常量:LOCATION_PROPERTY = \"spring.config.location\
AnsiOutputApplicationListener设置ansi编码格式输出
ClassLoader classLoader = getClassLoader()获取类加载器,如果成员变量中的类加载器为null,则返回ClassUtils.getDefaultClassLoader()
第五步
BackgroundPreinitializer初始化一些转换解析器
stepName=\"spring.boot.application.environment-prepared\"listenerAction=span style=\"font-size: inherit;\
Banner banner = getBanner(environment)获取banner对象
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)初始化默认应用参数类,例如java -jar --spring.profiles.active=prod
启动类SpringApplication.run
第二步
PropertiesPropertySourceLoader、YamlPropertySourceLoader用于加载yaml文件和properties文件,它们的顺序也为配置文件的优先级,并且该类维护了一些读取配置文件的常量CONFIG_NAME_PROPERTY = \"spring.config.name\" ,可通过配置此属性修改扫描配置的文件名,例如: java -jar myproject.jar --spring.config.name=myprojectDEFAULT_CONFIG_NAMES = { \"application\" },该配置为默认的配置文件名称
configureHeadlessProperty();设置系统参数:java.awt.headless(在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式,例如Linux服务器)
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext()构造默认启动器上下文
DelegatingApplicationListener未执行任何操作
EventPublishingRunListener span style=\"font-size: inherit;\
此处banner判断bannerMode是否是OFF模式,如果是则直接返回,
Banner printedBanner = printBanner(environment)获取并打印banner,并返回生成的PrintedBanner实例
将每个文件遍历,按key-value形式读取工厂名称,并将它们去重并存入到result中,再将result存入到缓存中
另起线程(Thread.start())初始化解析转换器,每个解析转换器初始化也从另起的线程里再起线程:runSafely(new ConversionServiceInitializer()); runSafely(new ValidationInitializer()); runSafely(new MessageConverterInitializer()); runSafely(new JacksonInitializer()); runSafely(new CharsetInitializer());
deduceEnvironmentClass()通过判断应用类型(this.webApplicationType),返回对应的class对象,由于此应用属于SERVLET,故返回StandardServletEnvironment.class
在new ApplicationConversionService()时,会执行以下初始化转化器和格式化器的操作,共137个DefaultConversionService.addDefaultConverters(registry); DefaultFormattingConversionService.addDefaultFormatters(registry); addApplicationFormatters(registry); addApplicationConverters(registry);
this.webApplicationType = WebApplicationType.deduceFromClasspath()判断当前web应用类型,类型包括:NONE、SERVLET、REACTIVE此时为SERVLET
此时,listeners仅包括EventPublishingRunListener
此时,environment的sources中有6个source,按顺序分别为configurationProperties、servletConfigInitParams、servletContextInitParams、systemProperties、systemEnvironment、random
applicationStartup = ApplicationStartup.DEFAULTcontext.setApplicationStartup(this.applicationStartup)为此应用上下文设置应用程序启动,这允许应用程序上下文在启动期间记录指标
StopWatch stopWatch = new StopWatch();\t\tstopWatch.start();开始启动计时
PropertiesPropertySourceLoader中维护了properties、xml的后缀
configureIgnoreBeanInfo(environment)配置需要忽略的Bean信息从应用环境中取\"spring.beaninfo.ignore\"属性,由于属性为null,故取默认值TRUE,并将TRUE设置到System的\"spring.beaninfo.ignore\"属性中
EnvironmentPostProcessorApplicationListener识别到事件为ApplicationEnvironmentPreparedEvent,执行onApplicationEnvironmentPreparedEvent(event)方法
StandardServletEnvironment继承自StandardEnvironmentStandardEnvironment继承自AbstractEnvironmentStandardServletEnvironment中配置了servletContextInitParams、servletConfigInitParams、jndiProperties等属性StandardEnvironment中配置了systemEnvironment、systemProperties等属性AbstractEnvironment中配置了spring.profiles.*等属性,构造方法中初始化了StandardServletEnvironment和StandardEnvironment的4个属性到它的propertySources变量中分别为:servletConfigInitParams、servletContextInitParams、systemProperties、systemEnvironment
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources))初始化加载类资源集合,这里的primarySources为启动类
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class))设置监听器,共9个
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class))设置应用上下文初始化器,加载完成后共7个
返回图片类型banner1、从environment中获取spring.banner.image.location属性若该属性不为空,加载图片并返回,若找不到图片返回null。2、遍历查找banner.gif/jpg/png,若能找到则返回3、返回null
DebugAgentEnvironmentPostProcessor未执行任何操作
ConfigurationPropertySources.attach(environment)使环境参数匹配环境
ConfigurationWarningsApplicationContextInitializerContextIdApplicationContextInitializerDelegatingApplicationContextInitializerRSocketPortInfoApplicationContextInitializerServerPortInfoApplicationContextInitializerSharedMetadataReaderFactoryContextInitializerConditionEvaluationReportLoggingListener
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION)加载所有META-INF/spring.factories文件
new SpringApplication(primarySources).run(args)
this.bootstrappers =new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class))初始化启动加载器集合,完成此操作后,启动加载器列表为空
CloudFoundryVcapEnvironmentPostProcessor与云平台相关,由于环境不属于云平台,故未执行任何操作
context = createApplicationContext()创建应用上下文
this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext)); 调用所有的启动加载器通过启动器上下文初始化,由于new SpringApplication的第四步时,得到的启动器列表为空,故此处无启动加载器初始化
第三步
1、从environment中获取spring.banner.location属性若该属性为空,则去找banner.txt2、加载从1获取到的资源,如果资源存在,则返回该资源,否则返回null
SpringApplicationJsonEnvironmentPostProcessor允许spring.application.json属性的配置,该属性的优先级高于系统属性
第六步
初始化new SpringApplication(primarySources)
this.mainApplicationClass = deduceMainApplicationClass()设置主启动类
将加载到的配置文件进行扫描,获取里面的配置,并保存在类型为OriginTrackedMapPropertySource的propertySource中,并把该propertySource加入到环境中
BackgroundPreinitializer不进行任何处理
YamlPropertySourceLoader中维护了yml和yaml的后缀
第七步
此时sources中的配置属性资源已有5个,分别为:configurationProperties、servletConfigInitParams、servletContextInitParams、systemProperties、systemEnvironment注:它们是有序的
StartupStep step = this.applicationStartup.start(stepName);给step赋值为DefaultStartupStep
实例化StandardConfigDataLocationResolver
Banners banners = new Banners(); banners.addIfNotNull(getImageBanner(environment)); banners.addIfNotNull(getTextBanner(environment));生成新的Banners实例,并向其中加入图片类型的banner和文字类型的banner
判断banners中是否存在至少一个banner,若存在则返回,否则判断成员变量fallbackBanner是否有值,若有值则返回,否则返回默认Banner
将维护的6个类名实例化并排序,顺序见黄色注释,对他们进行遍历,执行span style=\"font-size: inherit;\
获取或创建应用环境ConfigurableEnvironment environment = getOrCreateEnvironment()
setInitializersthis.initializers = new ArrayList<>(initializers)
ClearCachesApplicationListenerParentContextCloserApplicationListenerFileEncodingApplicationListenerAnsiOutputApplicationListenerDelegatingApplicationListenerLoggingApplicationListenerEnvironmentPostProcessorApplicationListenerLiquibaseServiceLocatorApplicationListenerBackgroundPreinitializer
configureAdditionalProfiles(environment)设置环境中activeProfiles,若没有额外的profiles,则不执行任何操作
SpringApplicationRunListeners listeners = getRunListeners(args)生成所有spring运行监听器
执行run()方法
DefaultPropertiesPropertySource.moveToEnd(environment)将环境中propertySources中的defaultProperties移动到最后,但由于propertySources中没有defaultProperties,故未执行任何操作
FileEncodingApplicationListener未执行任何操作
0 条评论
回复 删除
下一页