ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

springbbot 启动流程

2022-07-21 15:04:10  阅读:200  来源: 互联网

标签:启动 创建 流程 boot webServer context springbbot servlet 加载


springbbot 启动流程

  1. SpringApplication.run(Application.class, args)

  2. new SpringApplication(primarySources) 生成一个springboot实例

    • 2.1 将传入的启动配置类保存起来

    • 2.2 判断应用类型

    • 2.3 使用springFactoryLoader加载 ApplicationContextInitializer.class类型的实例 保存起来 等会使用

    • 2.4 使用springFactoryLoader加载 ApplicationListener.class类型的实例 保存起来 等会使用
      默认springboot的核心包的spring.factory里面配置了一个该类型的类:EventPublishingRunListener 它保存了applicationListener集合
      当有什么事件 他就会像这些applicationListener转发

    • 2.5 检查main类位置

  3. 执行上面生产的实例的run(args)方法

    • 3.1 生成 StopWatch stopWatch.start(); 统计启动时长指标
    • 3.2 使用springFactoryLoader加载 SpringApplicationRunListeners.class类型的实例
      保存起来 等会使用 然后调用listener.start() 方法 表示启动springboot应用
    • 3.3 封装传入参数args 然后根据它来准备 environment 对象
      • 3.3.1 根据应用类型创建env
        servlert类型创建 StandardServletEnvironment()
        普通应用类型创建:StandardEnvironment()
      • 3.3.2 设置env 转换器
      • 3.3.3 配置 propertySource (Environment对象里面有个MutablePropertySources 而它是由List构成)
        将我们的args的参数格式化成PropertySource添加到Env里面 和 默认的参数格式化成PropertySource添加到Env里面
      • 3.3.4 配置Env那些配置是active的
    • 3.5 listeners.environmentPrepared(environment); 告诉listener准备环境
      这一步EventPublishingRunListener(类型 SpringApplicationListener) 会发布一个EnvPrepare事件
      然后符合条件的applicationListener类型的 实例 将会触发方法 其中 加载yaml和property配置文件的listenr为 ConfigFileApplicationListener
      它被指在springboot的核心包的spring.factory里面(spring-boot-x.x.x.jar) 所以当这一步后 env就有了我们的那些配置属性了
      顺便一说 propety的顺序比yaml要高
    • 3.6 context = createApplicationContext();创建context 根据应用类型来创建不同context类型 servlet 创建AnnotationConfigServletWebServerApplicationContext
      这个context 继承spring的 GenericWebApplicationContext 并且重写几个比较重要的方法 比如 onRefresh()方法:
    • 3.7 准备错误SpringBootExceptionReporter 来报告错误
    • 3.8 准备context prepareContext()
      • 3.8.1 设置context的env 为刚才准备的env对象
      • 3.8.2 应用ApplicationContextInitializer 这些对象的initialize(context); (ApplicationContextInitializer) 由初始化开始时 加载
      • 3.8.3 listeners.contextPrepared(context);通知listenner context已经准备好了
      • 3.8.4 如果设置了初始化懒加载 那么会在这一步著一个LazyInitializationBeanFactoryPostProcessor() 他会将没有明确定义加载方式的bean 定义为懒加载方式 默认为false
      • 3.8.5 将启动的配置类 注册到beanFactory 等待一会以它为源头 开始扫描项目的bean
      • 3.8.6 通知listeners.contextLoaded(context); context即将开始加载
    • 3.9 refreshContext(context); 刷新context 开始执行spring的那一套refresh 但是它稍微重写了context的一些方法
      • 3.9.1 重写了 onRefresh() 在这个阶段创建webserver
                @Override
              	protected void onRefresh() {
              		super.onRefresh();
              		try {
              			createWebServer();
              		}
              		catch (Throwable ex) {
              			throw new ApplicationContextException("Unable to start web server", ex);
              		}
              	}
      
           在这一步会创建 webServer 比如嵌入式TomcatServer 
       
         private void createWebServer() {
         		WebServer webServer = this.webServer;
         		ServletContext servletContext = getServletContext();
         		if (webServer == null && servletContext == null) {
         			
                  ServletWebServerFactory factory = getWebServerFactory();
                  根据依赖 自动创建webServer  创建的时候 放入了 ServletInitializer这个类 其实就是AnnotationConfigServletWebServerApplicationContext 的罗格lamda表达式 它的逻辑是 
                  当webserver启动时会找到容器中的ServletContextInitializer.class  类型 然后 调用他们的 beans.onStartup(servletContext);
                  对应的实现它能拿到ServletContext 利用它然后添加url映射 添加filter 添加listener等操作  实际上对应的DiapacherServlet就是在这里添加了webServer的映射
                  url: /  映射   DispatcherServlet 
      
         			this.webServer = factory.getWebServer(getSelfInitializer());
         		}
         		else if (servletContext != null) {
         			try {
         				getSelfInitializer().onStartup(servletContext);
         			}
         			catch (ServletException ex) {
         				throw new ApplicationContextException("Cannot initialize servlet context", ex);
         			}
         		}
         		initPropertySources();
         	}
         
       
      
            下面分析一波 springmvc的在springboot中的自动配置:
            1  首先在spring-boot-autoconfigure-x.x.x.jar包中的spring.factory 有如下配置:
            org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
            org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
            org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
            org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
            org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
            org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
         
            针对:.ServletWebServerFactoryAutoConfiguration,  会创建对应依赖的webServerFactory 比如TomcatServletWebServerFactory
            针对:ispatcherServletAutoConfiguration  他会创建一个DispatcherServlet 放入容器 
                 并且这个servlet还实现了 ApplicationContextAware 所以在创建过程中会吧context给它 后续它可以根据context的到它需要的mvc组件)
                 而这个servlet会被包装成ServletContextInitial类型放入容器 最终被Webserver初始化时调用到 
                 目的是往tomcat添加一个 一个映射所有的url(/)的Servelt 至此我们的前端拦截器配置完成 
      
            然后到了 WebMvcAutoConfiguration   由它来完成我们mvc与springboot的结合配置 它会根据我们的配置 往容器中添加一些mcv组件 比如 视图转换器 
            1 RequestMappingHandlerAdapter  请求映射调用适配器
            2 RequestMappingHandlerMapping  请求映射
            3 InternalResourceViewResolver  视图解析器
             。。。。等等
      
             在我们第一次通过网络请求访问时 就会触发DispatcherServlet的初始化 他会 调用如下方法 设置对应mvc组件 最后工作
         	protected void initStrategies(ApplicationContext context) {
      		initMultipartResolver(context);
      		initLocaleResolver(context);
      		initThemeResolver(context);
      		initHandlerMappings(context);
      		initHandlerAdapters(context);
      		initHandlerExceptionResolvers(context);
      		initRequestToViewNameTranslator(context);
      		initViewResolvers(context);
      		initFlashMapManager(context);
        	}
           
             
            
             
      
            
               
      
      
      
      • 3.9.2 重写了finshRefresh() 在刷新完毕后 启动webServer 发布一个启动事件
     @Override
     protected void finishRefresh() {
                super.finishRefresh();
                  WebServer webServer = startWebServer();
                if (webServer != null) {
                  publishEvent(new ServletWebServerInitializedEvent(webServer, this));
             }
     }
    
    • 3.10 afterRefresh() 在refresh完毕后 的动作 没有内容 留给别人扩展
    • 3.11 stopWatch.stop(); 启动统计结束
    • 3.12 listeners.started(context); 告诉listener context已经启动结束
    • 3.13 callRunners() 从容器中获得 ApplicationRunner.class 和 CommandLineRunner.class的实例 然后他们的fun方法
    • 3.14 listeners.running(context); 告诉listenr context已经开始运行了

标签:启动,创建,流程,boot,webServer,context,springbbot,servlet,加载
来源: https://www.cnblogs.com/pupansheng/p/16501908.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有