版權說明:本文檔由用戶提供并上傳,收益歸屬內(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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 護理質(zhì)量指標分析
- 小企業(yè)會計準則與企業(yè)所得稅法的差異分析
- 統(tǒng)計數(shù)據(jù)的描述
- 傳染病及其預防
- 六盤水瓷器修復培訓課件
- 早讀方法培訓
- 燒傷營養(yǎng)課件
- 籃球招生銷售培訓課件
- 公路運輸培訓課件
- 第六單元寫作《表達要得體》課件+2025-2026學年統(tǒng)編版語文八年級上冊
- 2024中考會考模擬地理(福建)(含答案或解析)
- 藥品追溯碼管理制度
- 腳手架國際化標準下的發(fā)展趨勢
- 購銷合同范本(塘渣)8篇
- 屋面光伏設計合同協(xié)議
- 生鮮業(yè)務采購合同協(xié)議
- GB/T 4340.2-2025金屬材料維氏硬度試驗第2部分:硬度計的檢驗與校準
- 銷售合同評審管理制度
- 資產(chǎn)評估員工管理制度
- 泳池突發(fā)安全事故應急預案
- 湖北省武漢市漢陽區(qū)2024-2025學年上學期元調(diào)九年級物理試題(含標答)
評論
0/150
提交評論