SpringBoot启动过程的实现
SpringBoot启动过程分析,首先打开SpringBoot的启用入口Main类:
@SpringBootApplication
publicclassApplicationMain{
publicstaticvoidmain(String[]args){
SpringApplication.run(ApplicationMain.class,args);
}
}
可以看到main方法里面只有一行核心启用类:SpringApplication.run(ApplicationMain.class,args);这个是关键,在改行打上断点,debug模式启动该main类。点击下一步进入SpringApplication的源码对应的run方法:
publicstaticConfigurableApplicationContextrun(Object[]sources,String[]args){
return(newSpringApplication(sources)).run(args);
}
初始化SpringApplication
SpringApplication实例化之前会调用构造方法进行初始化:
publicSpringApplication(Object...sources){
this.bannerMode=Mode.CONSOLE;
this.logStartupInfo=true;
this.addCommandLineProperties=true;
this.headless=true;
this.registerShutdownHook=true;
this.additionalProfiles=newHashSet();
this.initialize(sources);
}
而SpringApplication构造方法的核心是:this.initialize(sources);初始化方法,SpringApplication通过调用该方法来初始化。
privatevoidinitialize(Object[]sources){
if(sources!=null&&sources.length>0){
this.sources.addAll(Arrays.asList(sources));
}
this.webEnvironment=deduceWebEnvironment();
setInitializers((Collection)getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass=deduceMainApplicationClass();
}
1.deduceWebEnvironment方法是用来判断当前应用的环境,该方法通过获取这两个类来判断当前环境是否是web环境,如果能获得这两个类说明是web环境,否则不是。
javax.servlet.Servlet org.springframework.web.context.ConfigurableWebApplicationContext
2.getSpringFactoriesInstances方法主要用来从spring.factories文件中找出key为ApplicationContextInitializer的类并实例化,然后调用setInitializers方法设置到SpringApplication的initializers属性中。这个过程就是找出所有的应用程序初始化器。
privateCollectiongetSpringFactoriesInstances(Class type,Class>[]parameterTypes,Object...args){ ClassLoaderclassLoader=Thread.currentThread().getContextClassLoader(); Set names=newLinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type,classLoader)); List instances=this.createSpringFactoriesInstances(type,parameterTypes,classLoader,args,names); AnnotationAwareOrderComparator.sort(instances); returninstances; }
publicstaticListloadFactoryNames(Class>factoryClass,ClassLoaderclassLoader){ StringfactoryClassName=factoryClass.getName(); try{ //从spring.factories文件中找出key为ApplicationContextInitializer的类 Enumeration urls=classLoader!=null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayListresult=newArrayList(); while(urls.hasMoreElements()){ URLurl=(URL)urls.nextElement(); Propertiesproperties=PropertiesLoaderUtils.loadProperties(newUrlResource(url)); StringfactoryClassNames=properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } returnresult; }catch(IOExceptionvar8){ thrownewIllegalArgumentException("Unabletoload["+factoryClass.getName()+"]factoriesfromlocation["+"META-INF/spring.factories"+"]",var8); } }
当前的初始化器有如下几个:
3.同理调用getSpringFactoriesInstances从spring.factories文件中找出key为ApplicationListener的类并实例化,然后调用setListeners方法设置到SpringApplication的listeners属性中。这个过程就是找出所有的应用程序事件监听器。
当前的事件监听器有如下几个:
运行SpringApplication
初始化SpringApplication完成之后,调用run方法运行:
publicConfigurableApplicationContextrun(String...args){
//计时器,统计任务的执行时间
StopWatchstopWatch=newStopWatch();
//开始执行
stopWatch.start();
ConfigurableApplicationContextcontext=null;
FailureAnalyzersanalyzers=null;
this.configureHeadlessProperty();
//获取SpringApplicationRunListeners启动事件监听器,这里只有一个EventPublishingRunListener
SpringApplicationRunListenerslisteners=this.getRunListeners(args);
//封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听
listeners.starting();
try{
//构造一个应用程序参数持有类
ApplicationArgumentsapplicationArguments=newDefaultApplicationArguments(args);
//准备并配置环境
ConfigurableEnvironmentenvironment=this.prepareEnvironment(listeners,applicationArguments);
//打印banner图形
BannerprintedBanner=this.printBanner(environment);
//创建Spring容器
context=this.createApplicationContext();
newFailureAnalyzers(context);
//配置Spring容器
this.prepareContext(context,environment,listeners,applicationArguments,printedBanner);
//容器上下文刷新
this.refreshContext(context);
//容器创建完成之后调用afterRefresh方法
this.afterRefresh(context,applicationArguments);
//调用监听器,广播Spring启动结束的事件
listeners.finished(context,(Throwable)null);
//停止计时器
stopWatch.stop();
if(this.logStartupInfo){
(newStartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(),stopWatch);
}
returncontext;
}catch(Throwablevar9){
this.handleRunFailure(context,listeners,(FailureAnalyzers)analyzers,var9);
thrownewIllegalStateException(var9);
}
}
SpringApplicationRunListeners
1.获取启动事件监听器,可以看看该方法:
SpringApplicationRunListenerslisteners=this.getRunListeners(args);
privateSpringApplicationRunListenersgetRunListeners(String[]args){
Class>[]types=newClass[]{SpringApplication.class,String[].class};
returnnewSpringApplicationRunListeners(logger,this.getSpringFactoriesInstances(SpringApplicationRunListener.class,types,this,args));
}
同样的通过调用getSpringFactoriesInstances方法去META-INF/spring.factories文件中拿到SpringApplicationRunListener监听器,当前的SpringApplicationRunListener事件监听器只有一个EventPublishingRunListener广播事件监听器:
SpringApplicationRunListeners内部持有SpringApplicationRunListener集合和1个Log日志类。用于SpringApplicationRunListener监听器的批量执行。
SpringApplicationRunListener用于监听SpringApplication的run方法的执行,它定义了5个步骤:
1.starting:run方法执行的时候立马执行,对应的事件类型是ApplicationStartedEvent
2.environmentPrepared:ApplicationContext创建之前并且环境信息准备好的时候调用,对应的事件类型是ApplicationEnvironmentPreparedEvent
3.contextPrepared:ApplicationContext创建好并且在source加载之前调用一次,没有具体的对应事件
4.contextLoaded:ApplicationContext创建并加载之后并在refresh之前调用,对应的事件类型是ApplicationPreparedEvent
5.finished:run方法结束之前调用,对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent
SpringApplicationRunListener目前只有一个实现类EventPublishingRunListener,详见获取SpringApplicationRunListeners。它把监听的过程封装成了SpringApplicationEvent事件并让内部属性ApplicationEventMulticaster接口的实现类SimpleApplicationEventMulticaster广播出去,广播出去的事件对象会被SpringApplication中的listeners属性进行处理。
所以说SpringApplicationRunListener和ApplicationListener之间的关系是通过ApplicationEventMulticaster广播出去的SpringApplicationEvent所联系起来的
2.启动事件监听器
通过listeners.starting()可以启动事件监听器SpringApplicationRunListener,SpringApplicationRunListener是一个启动事件监听器接口:
publicinterfaceSpringApplicationRunListener{
voidstarting();
voidenvironmentPrepared(ConfigurableEnvironmentvar1);
voidcontextPrepared(ConfigurableApplicationContextvar1);
voidcontextLoaded(ConfigurableApplicationContextvar1);
voidfinished(ConfigurableApplicationContextvar1,Throwablevar2);
}
SpringApplicationRunListener接口的具体实现就是EventPublishingRunListener类,我们主要来看一下它的startting方法,该方法会封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听。
publicvoidstarting(){
this.initialMulticaster.multicastEvent(newApplicationStartedEvent(this.application,this.args));
}
配置并准备环境
privateConfigurableEnvironmentprepareEnvironment(
SpringApplicationRunListenerslisteners,
ApplicationArgumentsapplicationArguments){
//创建应用程序的环境信息。如果是web程序,创建StandardServletEnvironment;否则,创建StandardEnvironment
ConfigurableEnvironmentenvironment=getOrCreateEnvironment();
//配置环境信息。比如profile,命令行参数
configureEnvironment(environment,applicationArguments.getSourceArgs());
//广播出ApplicationEnvironmentPreparedEvent事件给相应的监听器执行
listeners.environmentPrepared(environment);
//环境信息的校对
if(!this.webEnvironment){
environment=newEnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
returnenvironment;
}
判断环境,如果是web程序,创建StandardServletEnvironment;否则,创建StandardEnvironment。
privateConfigurableEnvironmentgetOrCreateEnvironment(){
if(this.environment!=null){
returnthis.environment;
}else{
return(ConfigurableEnvironment)(this.webEnvironment?newStandardServletEnvironment():newStandardEnvironment());
}
}
创建Spring容器上下文
protectedConfigurableApplicationContextcreateApplicationContext(){
Class>contextClass=this.applicationContextClass;
if(contextClass==null){
try{
//判断是否是web应用,
//如果是则创建AnnotationConfigEmbeddedWebApplicationContext,否则创建AnnotationConfigApplicationContext
contextClass=Class.forName(this.webEnvironment
?DEFAULT_WEB_CONTEXT_CLASS:DEFAULT_CONTEXT_CLASS);
}
catch(ClassNotFoundExceptionex){
thrownewIllegalStateException(
"UnablecreateadefaultApplicationContext,"
+"pleasespecifyanApplicationContextClass",
ex);
}
}
return(ConfigurableApplicationContext)BeanUtils.instantiate(contextClass);
}
配置Spring容器上下文
privatevoidprepareContext(ConfigurableApplicationContextcontext,
ConfigurableEnvironmentenvironment,SpringApplicationRunListenerslisteners,
ApplicationArgumentsapplicationArguments,BannerprintedBanner){
//设置Spring容器上下文的环境信息
context.setEnvironment(environment);
//Spring容器创建之后做一些额外的事
postProcessApplicationContext(context);
//SpringApplication的初始化器开始工作
applyInitializers(context);
//遍历调用SpringApplicationRunListener的contextPrepared方法。目前只是将这个事件广播器注册到Spring容器中
listeners.contextPrepared(context);
if(this.logStartupInfo){
logStartupInfo(context.getParent()==null);
logStartupProfileInfo(context);
}
//把应用程序参数持有类注册到Spring容器中,并且是一个单例
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
if(printedBanner!=null){
context.getBeanFactory().registerSingleton("springBootBanner",printedBanner);
}
//加载sources,sources是main方法所在的类
Set
Spring容器创建之后回调方法postProcessApplicationContext
protectedvoidpostProcessApplicationContext(ConfigurableApplicationContextcontext){
//如果SpringApplication设置了实例命名生成器,则注册到Spring容器中
if(this.beanNameGenerator!=null){
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
//如果SpringApplication设置了资源加载器,设置到Spring容器中
if(this.resourceLoader!=null){
if(contextinstanceofGenericApplicationContext){
((GenericApplicationContext)context)
.setResourceLoader(this.resourceLoader);
}
if(contextinstanceofDefaultResourceLoader){
((DefaultResourceLoader)context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
}
初始化器开始工作
protectedvoidapplyInitializers(ConfigurableApplicationContextcontext){
//遍历每个初始化器,调用对应的initialize方法
for(ApplicationContextInitializerinitializer:getInitializers()){
Class>requiredType=GenericTypeResolver.resolveTypeArgument(
initializer.getClass(),ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType,context,"Unabletocallinitializer.");
initializer.initialize(context);
}
}
Spring容器创建完成之后会调用afterRefresh方法
ApplicationRunner、CommandLineRunner类都是在在afterRefresh方法中调用的,也就是说在Spring容器创建之后执行的。
protectedvoidapplyInitializers(ConfigurableApplicationContextcontext){
//遍历每个初始化器,调用对应的initialize方法
for(ApplicationContextInitializerinitializer:getInitializers()){
Class>requiredType=GenericTypeResolver.resolveTypeArgument(
initializer.getClass(),ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType,context,"Unabletocallinitializer.");
initializer.initialize(context);
}
}
参考:https://blog.wangqi.love/articles/Spring/SpringBoot启动过程.html
到此这篇关于SpringBoot启动过程的实现的文章就介绍到这了,更多相关SpringBoot启动过程内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。