首页 文章资讯内容详情

SpringBoot-启动流程

2026-06-01 4 花语

本文内容纲要:

-SpringBoot-启动流程 -启动 -启动类 -初始化配置 -创建应用上下文 -刷新应用上下文 -配置工厂对象,包括上下文类加载器,bean工厂发布处理器 -注册并实例化bean工厂发布处理器,并调用他们 -注册并实例化bean发布处理器 -初始化一些与上下文有特别关系的bean对象 -实例化所有bean工厂缓存的bean对象 -发布通知-通知上下文刷新完成 -通知监听者-启动程序完成

SpringBoot-启动流程

平时开发springboot项目的时候,一个SpringBootApplication注解加一个main方法就可以启动服务器运行起来(默认tomcat),看了下源码,这里讲下认为主要的流程

主要流程如下

0.启动main方法开始

1.初始化配置:通过类加载器,(loadFactories)读取classpath下所有的spring.factories配置文件,创建一些初始配置对象;通知监听者应用程序启动开始,创建环境对象environment,用于读取环境配置如application.yml

2.创建应用程序上下文-createApplicationContext,创建bean工厂对象

3.刷新上下文(启动核心)

3.1配置工厂对象,包括上下文类加载器,对象发布处理器,beanFactoryPostProcessor

3.2注册并实例化bean工厂发布处理器,并且调用这些处理器,对包扫描解析(主要是class文件)

3.3注册并实例化bean发布处理器beanPostProcessor

3.4初始化一些与上下文有特别关系的bean对象(创建tomcat服务器)

3.5实例化所有bean工厂缓存的bean对象(剩下的)

3.6发布通知-通知上下文刷新完成(启动tomcat服务器)

4.通知监听者-启动程序完成

启动中,大部分对象都是BeanFactory对象通过反射创建

SpringBoot的启动解析代码过多,下文是整体流程的部分主要代码

启动

启动程序:

importorg.springframework.boot.SpringApplication;//启动类 importorg.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication//启动必要注解 publicclassYourApplication{ //运行main方法启动springboot publicstaticvoidmain(String[]args){ SpringApplication.run(YourApplication.class,args);//启动类静态run方法 } }

启动类

org.springframework.boot.SpringApplication包含主流程方法

启动类在运行静态run方法的时候,是先创建一个SpringApplication对象,再运行对象的run方法,工厂初始配置在构造函数中完成,run方法定义运行总体流程

//静态方法org.springframework.boot.SpringApplication.run(Class<?>[],String[]) publicstaticConfigurableApplicationContextrun(Class<?>[]primarySources,String[]args){ returnnewSpringApplication(primarySources).run(args); } //构造方法 publicSpringApplication(ResourceLoaderresourceLoader,Class<?>...primarySources){ //.......... ////1.(loadFactories)读取classpath下所有的spring.factories配置文件//// //配置应用程序启动前的初始化对象 setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class)); //配置应用程序启动前的监听器 setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass=deduceMainApplicationClass(); } //对象run方法开始启动程序 publicConfigurableApplicationContextrun(String...args){ //...... //通知监听者启动开始 listeners.starting(); try{ //创建应用程序环境配置文件在此处读取(application.propertiesapplication.yml) ConfigurableEnvironmentenvironment=prepareEnvironment(listeners,applicationArguments); ////2.创建应用程序上下文...此处创建了beanfactory//// context=createApplicationContext(); ////3.刷新上下文(spring启动核心)//// refreshContext(context); ////4.启动完成通知......//// listeners.started(context); } catch(Throwableex){ handleRunFailure(context,ex,exceptionReporters,listeners); thrownewIllegalStateException(ex); } try{ listeners.running(context); } catch(Throwableex){ handleRunFailure(context,ex,exceptionReporters,null); thrownewIllegalStateException(ex); } returncontext; }

初始化配置

springboot启动应用程序之前,会创建一些初始化对象和监听器

这个操作在构造方法中完成,根据配置文件,创建ApplicationContextInitializer.class,ApplicationListener.class两个接口的实现类,至于具体创建那些类对象,根据下面的方法逻辑去做

org.springframework.boot.SpringApplication.getSpringFactoriesInstances()->

org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames()->

org.springframework.core.io.support.SpringFactoriesLoader.loadSpringFactories()->

createSpringFactoriesInstances() //构造方法中的初始化对象创建 setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class)); //看一下getSpringFactoriesInstances方法 private<T>Collection<T>getSpringFactoriesInstances(Class<T>type){ returngetSpringFactoriesInstances(type,newClass<?>[]{}); } private<T>Collection<T>getSpringFactoriesInstances(Class<T>type,Class<?>[]parameterTypes,Object...args){ ClassLoaderclassLoader=getClassLoader(); //获取初始化类的类名 Set<String>names=newLinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type,classLoader)); //通过这些类名实例化对象 List<T>instances=createSpringFactoriesInstances(type,parameterTypes,classLoader,args,names); AnnotationAwareOrderComparator.sort(instances); returninstances; } //读取配置方法 //更详深层的代码在org.springframework.core.io.support.SpringFactoriesLoader.loadSpringFactories(ClassLoader) publicstaticList<String>loadFactoryNames(Class<?>factoryType,@NullableClassLoaderclassLoader){ StringfactoryTypeName=factoryType.getName(); returnloadSpringFactories(classLoader).getOrDefault(factoryTypeName,Collections.emptyList()); } //loadSpringFactories(classLoader)读取运行环境中所有META-INF/spring.factories配置

通过上面的方法,

spring-boot-2.2.8.RELEASE.jar/META-INF/spring.factories的文件中是这样,

#ApplicationContextInitializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\ org.springframework.boot.context.ContextIdApplicationContextInitializer,\ org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\ org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\ org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

如果只读取这一个文件,loadFactoryNames(ApplicationContextInitializer.class,classLoader)读取返回的就是下面的数组:

[org.springframework.context.ApplicationContextInitializer, org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer, org.springframework.boot.context.ContextIdApplicationContextInitializer, org.springframework.boot.context.config.DelegatingApplicationContextInitializer, org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer]

通过Class.forName(className)获取这些类的Class,最后反射newInstance创建这些对象

创建好这些对象后,启动监听器

listeners.starting();//这里也是一些调用操作

读取application配置

监听器启动之后,会读取application.properties或者application.yml文件

ConfigurableEnvironmentenvironment=prepareEnvironment(listeners,applicationArguments);//此处application.properties配置文件会被读取

创建应用上下文

初始化和配置好后,开始创建应用程序上下文,createApplicationContext,关键的工厂BeanFactory就是此处创建,具体逻辑如下

//创建应用程序上下文 context=createApplicationContext(); protectedConfigurableApplicationContextcreateApplicationContext(){ //上下文创建的判断逻辑 Class<?>contextClass=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); } publicstaticfinalStringDEFAULT_SERVLET_WEB_CONTEXT_CLASS="org.springframework.boot." +"web.servlet.context.AnnotationConfigServletWebServerApplicationContext"; //默认是创建这个类

这里通过this.webApplicationType判断创建具体的应用上下文,也是反射创建对象,默认创建的是org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext对象,看一下这个类的基本信息

publicclassAnnotationConfigServletWebServerApplicationContextextendsServletWebServerApplicationContext implementsAnnotationConfigRegistry{ //构造方法 publicAnnotationConfigServletWebServerApplicationContext(){ this.reader=newAnnotatedBeanDefinitionReader(this); this.scanner=newClassPathBeanDefinitionScanner(this); } }

创建工厂对象

此类实现了很多接口,其中一个超父类是org.springframework.context.support.GenericApplicationContext

jvm机制,创建对象的时候,先运行父类的构造方法,所以创建了beanFactory //超级父类GenericApplicationContext的构造方法 publicGenericApplicationContext(){ this.beanFactory=newDefaultListableBeanFactory();//创建工厂对象 }

刷新应用上下文

创建好上下文之后,开始刷新上下文,这里做了很多

工厂配置,bean处理器配置,类的扫描,解析,bean定义,bean类信息缓存,服务器创建,bean实例化,动态代理对象的创建等,

spring中注册bean信息和实例化bean是两件事情。

注册bean信息不是创建bean对象,是解析bean类获取详细信息,会创建BeanDefinition对象,携带bean类的字节码和方法等信息,把BeanDefinition对象注册保存到工厂BeanDefinitionMap中。

工厂实例化bean时直接BeanDefinitionMap.get(beanName)获取bean的字节码信息,通过反射创建对象,然后将bean对象保存到singletonObjects中。

refreshContext(context);//刷新上下文

默认实际对应的是org.springframework.context.support.AbstractApplicationContext类的refresh()方法

@Override publicvoidrefresh()throwsBeansException,IllegalStateException{ synchronized(this.startupShutdownMonitor){ //...... //3.1配置工厂对象 prepareBeanFactory(beanFactory); try{ postProcessBeanFactory(beanFactory); //3.2注册并实例化bean工厂处理器,并调用他们 invokeBeanFactoryPostProcessors(beanFactory); //3.3注册并实例化bean处理器 registerBeanPostProcessors(beanFactory); //3.4初始化一些与上下文有特别关系的bean对象(创建tomcat) onRefresh(); //3.5实例化所有bean工厂缓存的bean对象(剩下的). finishBeanFactoryInitialization(beanFactory); //3.6发布通知-通知上下文刷新完成(包括启动tomcat) finishRefresh(); } catch(BeansExceptionex){//......Propagateexceptiontocaller. throwex; } finally{//...... resetCommonCaches(); } } }

配置工厂对象,包括上下文类加载器,bean工厂发布处理器

工厂创建好后,首先配置的是类加载器,然后是一些对象发布处理器(拦截器)

////3.1配置工厂对象 prepareBeanFactory(beanFactory); protectedvoidprepareBeanFactory(ConfigurableListableBeanFactorybeanFactory){ //设置类加载器 beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(newStandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(newResourceEditorRegistrar(this,getEnvironment())); //添加BeanPostProcessor beanFactory.addBeanPostProcessor(newApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); //...... } }

注册并实例化bean工厂发布处理器,并调用他们

过程主要是工厂发布处理器的创建和调用,逻辑较多

////3.2注册并实例化bean工厂处理器,并调用他们 invokeBeanFactoryPostProcessors(beanFactory); protectedvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory){ PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors()); //...... } //PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors publicstaticvoidinvokeBeanFactoryPostProcessors( ConfigurableListableBeanFactorybeanFactory,List<BeanFactoryPostProcessor>beanFactoryPostProcessors){ postProcessorNames=beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false); for(StringppName:postProcessorNames){ if(!processedBeans.contains(ppName)&&beanFactory.isTypeMatch(ppName,Ordered.class)){ //创建BeanDefinitionRegistryPostProcessor处理器 currentRegistryProcessors.add(beanFactory.getBean(ppName,BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //调用这些处理器 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors,registry); //... } //循环调用 privatestaticvoidinvokeBeanDefinitionRegistryPostProcessors( Collection<?extendsBeanDefinitionRegistryPostProcessor>postProcessors,BeanDefinitionRegistryregistry){ for(BeanDefinitionRegistryPostProcessorpostProcessor:postProcessors){ postProcessor.postProcessBeanDefinitionRegistry(registry); } }

BeanDefinitionRegistryPostProcessor的子类对象在此处创建并调postProcessBeanDefinitionRegistry方法。

其中org.springframework.context.annotation.ConfigurationClassPostProcessor就是BeanDefinitionRegistryPostProcessor的子类,是一个spring的类解析器,扫描包下所有的类,解析出bean类,注册到bean工厂由此类主要参与,其中有不少递归

注册并实例化bean发布处理器

////3.3注册并实例化bean处理器 registerBeanPostProcessors(beanFactory);

BeanFactoryPostProcessors和BeanPostProcessors是有区别的

BeanFactoryPostProcessors是工厂发布处理器,定义什么是bean,知道哪些是bean类,解析class文件,包括注解解析,成员对象依赖解析等;BeanPostProcessors主要在BeanFactoryPostProcessors调用完之后工作

一般在bean对像的创建之前或之后,BeanFactory调用这些bean处理器拦截处理,Spring代理对象的创建也是通过beanPostProcessor处理器来实现

bean发布处理器生产AOP代理对象

AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessors,在bean被工厂创建之后,BeanFactory调用拦截器的postProcessAfterInitialization做拦截处理。此拦截器处理器实际执行的是父类org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator的方法

比如一个UserServiceImp类有@service注解,并且有切点Aspectj注解增强方法,bean工厂创建userServiceImp后,代理拦截器检测到AOP相关注解,会创建动态代理对象userServiceImp$$EnhancerBySpringCGLIB并返代理对象,而不是返回userServiceImp

Spring工厂部分bean创建拦截代码逻辑

//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(String,Object,RootBeanDefinition) //bean初始化 protectedObjectinitializeBean(StringbeanName,Objectbean,@NullableRootBeanDefinitionmbd){ invokeAwareMethods(beanName,bean); ObjectwrappedBean=bean; if(mbd==null||!mbd.isSynthetic()){ //初始化之前,拦截 wrappedBean=applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName); } invokeInitMethods(beanName,wrappedBean,mbd); if(mbd==null||!mbd.isSynthetic()){ //初始化之后拦截 wrappedBean=applyBeanPostProcessorsAfterInitialization(wrappedBean,beanName); } returnwrappedBean; } @Override publicObjectapplyBeanPostProcessorsAfterInitialization(ObjectexistingBean,StringbeanName) throwsBeansException{ Objectresult=existingBean; for(BeanPostProcessorprocessor:getBeanPostProcessors()){ //循环bean发布处理器调用postProcessAfterInitialization方法 Objectcurrent=processor.postProcessAfterInitialization(result,beanName); if(current==null){ returnresult; } result=current; } returnresult; }

AbstractAutoProxyCreator在此循环中被调用,比如在userServiceImp服务类上有事务注解@Transactional,一般就会被拦截生成代理对象,添加额外的处理事务的功能代码,返回增强的代理对象

初始化一些与上下文有特别关系的bean对象

默认tomcat服务器的创建就是此方法完成,此处定义特别的bean创建,一般是服务器有关或个性化对象,

////3.4初始化一些与上下文有特别关系的bean对象 onRefresh(); //org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext //子类context重写 @Override protectedvoidonRefresh(){ super.onRefresh(); try{ createWebServer();//创建服务器 } catch(Throwableex){ thrownewApplicationContextException("Unabletostartwebserver",ex); } } privatevoidcreateWebServer(){ WebServerwebServer=this.webServer; ServletContextservletContext=getServletContext(); if(webServer==null&&servletContext==null){ ServletWebServerFactoryfactory=getWebServerFactory(); this.webServer=factory.getWebServer(getSelfInitializer()); //默认创建tomcat服务器 //org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer() } //...... initPropertySources(); }

实例化所有bean工厂缓存的bean对象

服务器启动后,创建spring工厂里面缓存的bean信息(没有被创建的单例)

////3.5实例化所有bean工厂缓存的bean对象(剩下的). finishBeanFactoryInitialization(beanFactory); protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactorybeanFactory){ //...... //Instantiateallremaining(non-lazy-init)singletons. beanFactory.preInstantiateSingletons(); } //子类org.springframework.beans.factory.support.DefaultListableBeanFactory实现方法,完成剩下的单例bean对象创建 @Override publicvoidpreInstantiateSingletons()throwsBeansException{ List<String>beanNames=newArrayList<>(this.beanDefinitionNames); for(StringbeanName:beanNames){ RootBeanDefinitionbd=getMergedLocalBeanDefinition(beanName); if(!bd.isAbstract()&&bd.isSingleton()&&!bd.isLazyInit()){ getBean(beanName);//创建还没有实例化的bean对象 } } }

发布通知-通知上下文刷新完成

上下文初始化完成之后,启动tomcat服务器

finishRefresh(); //super.finishRefresh protectedvoidfinishRefresh(){ //......发布刷行完成事件 //Publishthefinalevent. publishEvent(newContextRefreshedEvent(this)); } //org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh() @Override protectedvoidfinishRefresh(){ super.finishRefresh(); WebServerwebServer=startWebServer();//启动服务器 if(webServer!=null){ publishEvent(newServletWebServerInitializedEvent(webServer,this)); } }

通知监听者-启动程序完成

发布通知监听器启动完成,监听器会根据事件类型做个性化操作

listeners.started(context); listeners.running(context); voidstarted(ConfigurableApplicationContextcontext){ for(SpringApplicationRunListenerlistener:this.listeners){ listener.started(context); } } voidrunning(ConfigurableApplicationContextcontext){ for(SpringApplicationRunListenerlistener:this.listeners){ listener.running(context); } } @Override publicvoidstarted(ConfigurableApplicationContextcontext){ context.publishEvent(newApplicationStartedEvent(this.application,this.args,context)); } @Override publicvoidrunning(ConfigurableApplicationContextcontext){ context.publishEvent(newApplicationReadyEvent(this.application,this.args,context)); }

不定期更新...

本文内容总结:SpringBoot-启动流程,启动,启动类,初始化配置,创建应用上下文,刷新应用上下文,配置工厂对象,包括上下文类加载器,bean工厂发布处理器,注册并实例化bean工厂发布处理器,并调用他们,注册并实例化bean发布处理器,初始化一些与上下文有特别关系的bean对象,实例化所有bean工厂缓存的bean对象,发布通知-通知上下文刷新完成,通知监听者-启动程序完成,

原文链接:https://www.cnblogs.com/Narule/p/14253754.html