SpringBoot启动流程

<?xml version="1.0" encoding="UTF-8" ?>
<root>

    <a comment="SpringApplication.run(AppMain.class, args)">
        <b comment="new SpringApplication(AppMain.class).run(args)" remark="主要就是看run(args)">
            <b1 comment="new SpringApplication(AppMain.class)">
                判断当前启动模式:NONE,SERVLET,REACTIVE
                类加载器加载META-INF/factories,一共有两个,SpringBoot的一个,Spring的一个
                C:\MavenRepository\org\springframework\boot\spring-boot\2.7.0\spring-boot-2.7.0\META-INF
                C:/MavenRepository/org/springframework/spring-beans/5.3.20/spring-beans-5.3.20.jar!/META-INF/spring.factories
                然后做成一个Map<AppClassLoder,Map<META-INF/factories的interface,interface的实现类的集合>>
                然后加载BootstrapRegistryInitializer,ApplicationContextInitializer,ApplicationListener这三个key的无参构造函数
                     进入SpringApplication的属性中,后面run(args)中会调用到
                最后记录mainApplicationClass=AppMain.class
            </b1>
            <b2 comment="run(args)">
                记录启动时间
                根据启动模式为Servlet,创建ApplicationServletEnvironment。准备环境,例如args,也就是如果你没额外配置参数,其实这些都没啥用。
                配置环境相关时,有setConversionServer,例如配置的String转成Date之类一共137个
                listeners.environmentPrepared(bootstrapContext, environment);把spring.profiles.active取出来了
                打印banner图:如果是图片,就转成ASCII码打印出来
                <createApplicationContext>
                    ApplicationContextFactory(interceface)中有变量ApplicationContextFactory DEFAULT的初始化
                        =通过之前的META-INF/factories读取ApplicationContextFactory创建出org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
                    在该ApplicationContextFactory构造函数中,有将注解扫描的方式的具体类设置进去this.render  this.scanner以及其他的一些过滤处理之类的类的对象实例
                </createApplicationContext>
                <prepareContext>
                    调用之前的environment,ApplicationContextInitializer,ApplicationListener进行处理。
                    然后打印应用信息:logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);
                    将AppMain加载成一个bean(这里就涉及到详细的如何装载一个bean,可以详细看看,主要是在load(context, sources.toArray(new Object[0]));)
                    将之前存着的trace日志的List清空
                </prepareContext>
                <refreshContext remark="这个是最核心的方法,归属于Spring框架而不是SpringBoot的">
                    <prepareRefresh>
                        将之前的Environment,listeners进行下处理
                    </prepareRefresh>
                    <obtainFreshBeanFactory>
                        创建新的DefaultListableBeanFactory,有的话会销毁旧的。并且将所有bean的BeanDefinition信息加载进入BeanFactory中。
                        <loadBeanDefinitions remark="这个是核心">根据XML或者注解</loadBeanDefinitions>
                    </obtainFreshBeanFactory>
                     <prepareBeanFactory>
                        设置SPEL表达式解析器
                        addPropertyEditorRegistrar,addBeanPostProcessor
                        ignoreDependencyInterface,registerResolvableDependency
                        简而言之,就是给BeanFactory设置属性值进行初始化。
                    </prepareBeanFactory>
                    <postProcessBeanFactory>
                        给BeanFacotry的对象设置了一些值
                    </postProcessBeanFactory>
                    <invokeBeanFactoryPostProcessors>
                        就像bean的生命周期有BeanPostProcessor,BeanFactory也有BeanFactoryPostProcessor,只不过bean的postProcessor有beforeInit和afterInit,
                            而BeanFacotry的postPorcessor只有after
                    </invokeBeanFactoryPostProcessors>
                    <registerBeanPostProcessors>
                        Instance and register all BeanPostProcessor beans,暂时不调用BeanPostProcessor的方法
                    </registerBeanPostProcessors>
                    <finishBeanFactoryInitialization>
                        Instantiate all remaining (non-lazy-init) singletons.
                        核心是beanFactory.preInstantiateSingletons();
                    </finishBeanFactoryInitialization>
                    prepareBeanFactory:给DefaultListableBeanFactory设置各种值
                    onRefresh();this.webServer = factory.getWebServer(getSelfInitializer());Tomcat容器
                    this.finishBeanFactoryInitialization(beanFactory);全局异常处理、druid连接池
                </refreshContext></b2>
        </b>
    </a>
</root>

 

之前有想过学习SpringBoot相关的源码,包括Spring的核心、Tomcat、MyBatis。由于多少存在点技术支撑不足,而且大多是断断续续看了一周就没看了。

经过一段时间的技术沉淀,觉得没那么难了。打算重新看起。

 

posted on 2022-06-15 18:58  我欲皆真  阅读(857)  评论(0编辑  收藏  举报

导航