SpringBoot超詳細分析啟動流程_第1頁
SpringBoot超詳細分析啟動流程_第2頁
SpringBoot超詳細分析啟動流程_第3頁
SpringBoot超詳細分析啟動流程_第4頁
SpringBoot超詳細分析啟動流程_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

第SpringBoot超詳細分析啟動流程目錄1、創(chuàng)建SpringApplication1.1、判斷web類型1.2、加載上下文初始化器1.3、加載監(jiān)聽器1.4、獲得引導類類型2、執(zhí)行SpringApplication的run方法啟動Springboot2.1、準備environment2.1.1、創(chuàng)建environment2.1.2、配置environment2.2、打印Banner2.3、創(chuàng)建Spring上下文2.4、準備上下文2.4.1、ApplicationContext的后置處理2.4.2、應用初始化器2.4.3、獲取sources2.4.4、加載2.5、刷新上下文2.6、上下文刷新后2.7、執(zhí)行回調(diào)Springboot啟動類

@SpringBootApplication

publicclassTestApplication{

publicstaticvoidmain(String[]args){

SpringApplication.run(TestApplication.class,args);

SpringBootApplication注解

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan(excludeFilters={@Filter(type=FilterType.CUSTOM,classes=TypeExcludeFilter.class),

@Filter(type=FilterType.CUSTOM,classes=AutoConfigurationExcludeFilter.class)})

public@interfaceSpringBootApplication{

@SpringBootApplication注解上標注了@EnableAutoConfiguration,表示TestApplication是引導類。

Springboot的啟動方法中傳入了兩個參數(shù),引導類,和程序參數(shù)。

publicstaticConfigurableApplicationContextrun(ClassprimarySource,String...args){

returnrun(newClass[]{primarySource},args);

調(diào)用run方法

publicstaticConfigurableApplicationContextrun(Class[]primarySources,String[]args){

returnnewSpringApplication(primarySources).run(args);

run方法中有兩步,創(chuàng)建SpringApplication和執(zhí)行SpringApplication的run方法。

1、創(chuàng)建SpringApplication

SpringApplication的構造器

publicSpringApplication(Class...primarySources){

this(null,primarySources);

privateResourceLoaderresourceLoader;

privateSetClassprimarySources;

publicSpringApplication(ResourceLoaderresourceLoader,Class...primarySources){

//將resourceLoader賦值成員變量,此處是null

this.resourceLoader=resourceLoader;

Assert.notNull(primarySources,"PrimarySourcesmustnotbenull");

//將引導類賦值成員變量

this.primarySources=newLinkedHashSet(Arrays.asList(primarySources));

//判斷web類型,賦值成員變量

this.webApplicationType=WebApplicationType.deduceFromClasspath();

//加載初始化器

setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));

//加載監(jiān)聽器

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

//獲得引導類

this.mainApplicationClass=deduceMainApplicationClass();

1.1、判斷web類型

//org.springframework.boot.WebApplicationType#deduceFromClasspath

staticWebApplicationTypededuceFromClasspath(){

//WEBFLUX_INDICATOR_CLASS="org.springframework.web.reactive.DispatcherHandler";

//JERSEY_INDICATOR_CLASS="org.glassfish.jersey.servlet.ServletContainer";

if(ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS,null)!ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS,null)

!ClassUtils.isPresent(JERSEY_INDICATOR_CLASS,null)){

returnWebApplicationType.REACTIVE;

//SERVLET_INDICATOR_CLASSES={"javax.servlet.Servlet",

"org.springframework.web.context.ConfigurableWebApplicationContext"}

for(StringclassName:SERVLET_INDICATOR_CLASSES){

if(!ClassUtils.isPresent(className,null)){

returnWebApplicationType.NONE;

returnWebApplicationType.SERVLET;

1.2、加載上下文初始化器

利用spi加載ApplicationContextInitializer的實現(xiàn)類

privateTCollectionTgetSpringFactoriesInstances(ClassTtype){

returngetSpringFactoriesInstances(type,newClass[]{});

privateTCollectionTgetSpringFactoriesInstances(ClassTtype,Class[]parameterTypes,Object...args){

//獲取classloader

ClassLoaderclassLoader=getClassLoader();

//Usenamesandensureuniquetoprotectagainstduplicates

//獲取配置文件中接口實現(xiàn)類的全限定名

SetStringnames=newLinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type,classLoader));

//初始化

ListTinstances=createSpringFactoriesInstances(type,parameterTypes,classLoader,args,names);

AnnotationAwareOrderComparator.sort(instances);

//返回

returninstances;

publicClassLoadergetClassLoader(){

if(this.resourceLoader!=null){

returnthis.resourceLoader.getClassLoader();

returnClassUtils.getDefaultClassLoader();

privateTListTcreateSpringFactoriesInstances(ClassTtype,Class[]parameterTypes,

ClassLoaderclassLoader,Object[]args,SetStringnames){

ListTinstances=newArrayList(names.size());

for(Stringname:names){

try{

ClassinstanceClass=ClassUtils.forName(name,classLoader);

Assert.isAssignable(type,instanceClass);

Constructorconstructor=instanceClass.getDeclaredConstructor(parameterTypes);

Tinstance=(T)BeanUtils.instantiateClass(constructor,args);

instances.add(instance);

catch(Throwableex){

thrownewIllegalArgumentException("Cannotinstantiate"+type+":"+name,ex);

returninstances;

將初始化好的上下文初始化器設置到成員變量

//privateListApplicationContextInitializerinitializers;

publicvoidsetInitializers(CollectionextendsApplicationContextInitializerinitializers){

this.initializers=newArrayList(initializers);

1.3、加載監(jiān)聽器

將初始化好的監(jiān)聽器設置到成員變量

//privateListApplicationListenerlisteners;

publicvoidsetListeners(CollectionextendsApplicationListenerlisteners){

this.listeners=newArrayList(listeners);

1.4、獲得引導類類型

privateClassdeduceMainApplicationClass(){

try{

StackTraceElement[]stackTrace=newRuntimeException().getStackTrace();

for(StackTraceElementstackTraceElement:stackTrace){

//獲取main方法的類

if("main".equals(stackTraceElement.getMethodName())){

returnClass.forName(stackTraceElement.getClassName());

catch(ClassNotFoundExceptionex){

//Swallowandcontinue

returnnull;

}

2、執(zhí)行SpringApplication的run方法啟動Springboot

publicConfigurableApplicationContextrun(String...args){

//啟動停止監(jiān)聽器

StopWatchstopWatch=newStopWatch();

stopWatch.start();

//Spring上下文

ConfigurableApplicationContextcontext=null;

//錯誤導出

CollectionSpringBootExceptionReporterexceptionReporters=newArrayList();

configureHeadlessProperty();

//運行時監(jiān)聽器

SpringApplicationRunListenerslisteners=getRunListeners(args);

//啟動運行時監(jiān)聽器

listeners.starting();

try{

//生成ApplicationArguments

ApplicationArgumentsapplicationArguments=newDefaultApplicationArguments(args);

//準備environment

ConfigurableEnvironmentenvironment=prepareEnvironment(listeners,applicationArguments);

configureIgnoreBeanInfo(environment);

//打印banner

BannerprintedBanner=printBanner(environment);

//創(chuàng)建Spring上下文

context=createApplicationContext();

exceptionReporters=getSpringFactoriesInstances(SpringBootExceptionReporter.class,

newClass[]{ConfigurableApplicationContext.class},context);

//準備上下文

prepareContext(context,environment,listeners,applicationArguments,printedBanner);

//刷新上下文

refreshContext(context);

//上下文刷新后

afterRefresh(context,applicationArguments);

//停止停止監(jiān)聽器

stopWatch.stop();

if(this.logStartupInfo){

newStartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),stopWatch);

//停止運行時監(jiān)聽器

listeners.started(context);

//執(zhí)行回調(diào)

callRunners(context,applicationArguments);

catch(Throwableex){

handleRunFailure(context,ex,exceptionReporters,listeners);

thrownewIllegalStateException(ex);

try{

listeners.running(context);

catch(Throwableex){

handleRunFailure(context,ex,exceptionReporters,null);

thrownewIllegalStateException(ex);

returncontext;

}

2.1、準備environment

privateConfigurableEnvironmentprepareEnvironment(SpringApplicationRunListenerslisteners,

ApplicationArgumentsapplicationArguments){

//Createandconfiguretheenvironment

//創(chuàng)建environment

ConfigurableEnvironmentenvironment=getOrCreateEnvironment();

//配置environment

configureEnvironment(environment,applicationArguments.getSourceArgs());

ConfigurationPropertySources.attach(environment);

listeners.environmentPrepared(environment);

bindToSpringApplication(environment);

if(!this.isCustomEnvironment){

environment=newEnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,

deduceEnvironmentClass());

ConfigurationPropertySources.attach(environment);

returnenvironment;

}

2.1.1、創(chuàng)建environment

privateConfigurableEnvironmentgetOrCreateEnvironment(){

if(this.environment!=null){

returnthis.environment;

switch(this.webApplicationType){

caseSERVLET:

returnnewStandardServletEnvironment();

caseREACTIVE:

returnnewStandardReactiveWebEnvironment();

default:

returnnewStandardEnvironment();

}

這里根據(jù)web類型創(chuàng)建不同的environment

2.1.2、配置environment

protectedvoidconfigureEnvironment(ConfigurableEnvironmentenvironment,String[]args){

if(this.addConversionService){

//轉(zhuǎn)換服務

ConversionServiceconversionService=ApplicationConversionService.getSharedInstance();

environment.setConversionService((ConfigurableConversionService)conversionService);

configurePropertySources(environment,args);

configureProfiles(environment,args);

配置PropertySources

protectedvoidconfigurePropertySources(ConfigurableEnvironmentenvironment,String[]args){

MutablePropertySourcessources=environment.getPropertySources();

if(this.defaultProperties!=null!this.defaultProperties.isEmpty()){

sources.addLast(newMapPropertySource("defaultProperties",this.defaultProperties));

if(this.addCommandLinePropertiesargs.length0){

Stringname=CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;

if(sources.contains(name)){

PropertySourcesource=sources.get(name);

CompositePropertySourcecomposite=newCompositePropertySource(name);

composite.addPropertySource(

newSimpleCommandLinePropertySource("springApplicationCommandLineArgs",args));

composite.addPropertySource(source);

sources.replace(name,composite);

else{

sources.addFirst(newSimpleCommandLinePropertySource(args));

主要為了在PropertySources添加一個SimpleCommandLinePropertySource。

配置profiles

protectedvoidconfigureProfiles(ConfigurableEnvironmentenvironment,String[]args){

SetStringprofiles=newLinkedHashSet(this.additionalProfiles);

profiles.addAll(Arrays.asList(environment.getActiveProfiles()));

environment.setActiveProfiles(StringUtils.toStringArray(profiles));

將profile添加到environment

2.2、打印Banner

privateBanner.ModebannerMode=Banner.Mode.CONSOLE;

privateBannerprintBanner(ConfigurableEnvironmentenvironment){

//無需打印

if(this.bannerMode==Banner.Mode.OFF){

returnnull;

ResourceLoaderresourceLoader=(this.resourceLoader!=null)this.resourceLoader

:newDefaultResourceLoader(getClassLoader());

SpringApplicationBannerPrinterbannerPrinter=newSpringApplicationBannerPrinter(resourceLoader,this.banner);

if(this.bannerMode==Mode.LOG){

returnbannerPrinter.print(environment,this.mainApplicationClass,logger);

returnbannerPrinter.print(environment,this.mainApplicationClass,System.out);

2.3、創(chuàng)建Spring上下文

//DEFAULT_SERVLET_WEB_CONTEXT_CLASS="org.springframework.boot."http://+"web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

//DEFAULT_REACTIVE_WEB_CONTEXT_CLASS="org.springframework."http://+"boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

//DEFAULT_CONTEXT_CLASS="org.springframework.context."

//+"annotation.AnnotationConfigApplicationContext";

protectedConfigurableApplicationContextcreateApplicationContext(){

ClasscontextClass=this.applicationContextClass;

if(contextClass==null){

try{

switch(this.webApplicationType){

caseSERVLET:

contextClass=Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);

break;

caseREACTIVE:

contextClass=Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);

break;

default:

contextClass=Class.forName(DEFAULT_CONTEXT_CLASS);

catch(ClassNotFoundExceptionex){

thrownewIllegalStateException(

"UnablecreateadefaultApplicationContext,pleasespecifyanApplicationContextClass",ex);

//初始化上下文并返回

return(ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);

}

2.4、準備上下文

privatevoidprepareContext(ConfigurableApplicationContextcontext,ConfigurableEnvironmentenvironment,

SpringApplicationRunListenerslisteners,ApplicationArgumentsapplicationArguments,BannerprintedBanner){

context.setEnvironment(environment);

//ApplicationContext的后置處理

postProcessApplicationContext(context);

//應用初始化器

applyInitializers(context);

//運行時監(jiān)聽器的準備上下文監(jiān)聽

listeners.contextPrepared(context);

if(this.logStartupInfo){

logStartupInfo(context.getParent()==null);

logStartupProfileInfo(context);

//Addbootspecificsingletonbeans

//獲取beanFactory

ConfigurableListableBeanFactorybeanFactory=context.getBeanFactory();

//將程序入?yún)⒆詁eanspringApplicationArguments

beanFactory.registerSingleton("springApplicationArguments",applicationArguments);

//將banner注冊beanspringBootBanner

if(printedBanner!=null){

beanFactory.registerSingleton("springBootBanner",printedBanner);

//設置BeanDefinition是否允許重寫

if(beanFactoryinstanceofDefaultListableBeanFactory){

((DefaultListableBeanFactory)beanFactory)

.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);

//初始化允許懶加載,設置BeanfactorypostProcessor

if(this.lazyInitialization){

context.addBeanFactoryPostProcessor(newLazyInitializationBeanFactoryPostProcessor());

//Loadthesources

//獲取source

SetObjectsources=getAllSources();

Assert.notEmpty(sources,"Sourcesmustnotbeempty");

load(context,sources.toArray(newObject[0]));

//運行時監(jiān)聽器,上下文加載完成

listeners.contextLoaded(context);

2.4.1、ApplicationContext的后置處理

protectedvoidpostProcessApplicationContext(ConfigurableApplicationContextcontext){

//注冊beanNameGenerator

if(this.beanNameGenerator!=null){

context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,

this.beanNameGenerator);

//注冊resourceLoader

if(this.resourceLoader!=null){

if(contextinstanceofGenericApplicationContext){

((GenericApplicationContext)context).setResourceLoader(this.resourceLoader);

if(contextinstanceofDefaultResourceLoader){

((DefaultResourceLoader)context).setClassLoader(this.resourceLoader.getClassLoader());

//設置ConversionService

if(this.addConversionService){

context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());

//org.springframework.boot.convert.ApplicationConversionService#getSharedInstance

publicstaticConversionServicegetSharedInstance(){

ApplicationConversionServicesharedInstance=ApplicationConversionService.sharedInstance;

if(sharedInstance==null){

synchronized(ApplicationConversionService.class){

sharedInstance=ApplicationConversionService.sharedInstance;

if(sharedInstance==null){

sharedInstance=newApplicationConversionService();

ApplicationConversionService.sharedInstance=sharedInstance;

returnsharedInstance;

2.4.2、應用初始化器

protectedvoidapplyInitializers(ConfigurableApplicationContextcontext){

for(ApplicationContextInitializerinitializer:getInitializers()){

ClassrequiredType=GenericTypeResolver.resolveTypeArgument(initializer.getClass(),

ApplicationContextInitializer.class);

Assert.isInstanceOf(requiredType,context,"Unabletocallinitializer.");

initializer.initialize(context);

執(zhí)行所有實現(xiàn)了ApplicationContextInitializer接口的類的initialize方法。

2.4.3、獲取sources

publicSetObjectgetAllSources(){

SetObjectallSources=newLinkedHashSet();

if(!CollectionUtils.isEmpty(this.primarySources)){

allSources.addAll(this.primarySources);

if(!CollectionUtils.isEmpty(this.sources)){

allSources.addAll(this.sources);

returnCollections.unmodifiableSet(allSources);

這里組裝了引導類和自定義的source

2.4.4、加載

protectedvoidload(ApplicationContextcontext,Object[]sources){

if(logger.isDebugEnabled()){

logger.debug("Loadingsource"+StringUtils.arrayToCommaDelimitedString(sources));

//創(chuàng)建BeanDefinitionLoader

BeanDefinitionLoaderloader=createBeanDefinitionLoader(getBeanDefinitionRegistry(context),s

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論