四,分析Spring Boot底层机制(Tomcat 启动分析+Spring容器初始化+Tomcat如 ...

打印 上一主题 下一主题

主题 897|帖子 897|积分 2691

四,分析Spring Boot底层机制(Tomcat 启动分析+Spring容器初始化+Tomcat如何关联 Spring 容器) 以及个人编写启动 Tomcat

@
目录

1. 源码分析 Spring Boot是如何启动 Tomcat ,并支持访问 @Controller 的 Debug 流程分析

进行源码分析,天然是少不了,Debug 的。下面就让我们打上断点 ,Debug起来吧
1.1 源码分析: SpringApplication.run( ) 方法
  1. SpringApplication.run()
  2. DeBug  SpringApplication.run(MainApp.class, args); 看看 Spring Boot 是如何启动 Tomcat的
复制代码
我们的Debug 目的:紧抓一条线,就是看到 tomcat 被启动的代码: 好比 tomcat.start()

  • SpringApplication.java

  1. // 这里我们开始 Debug SpringApplication。run()
  2.    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
  3.         return run(new Class[]{primarySource}, args);
  4.     }
复制代码

  • SpringApplication.java
  1.     public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
  2.         return (new SpringApplication(primarySources)).run(args);
  3.     }
复制代码
3.SpringApplication.java

  1. public ConfigurableApplicationContext run(String... args) {
  2.         StopWatch stopWatch = new StopWatch();
  3.         stopWatch.start();
  4.         DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
  5.         ConfigurableApplicationContext context = null;
  6.         this.configureHeadlessProperty();
  7.         SpringApplicationRunListeners listeners = this.getRunListeners(args);
  8.         listeners.starting(bootstrapContext, this.mainApplicationClass);
  9.         try {
  10.             ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  11.             ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
  12.             this.configureIgnoreBeanInfo(environment);
  13.             Banner printedBanner = this.printBanner(environment);
  14.             context = this.createApplicationContext();  // 特别分析: 创建容器
  15.             context.setApplicationStartup(this.applicationStartup);
  16.             this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
  17.             this.refreshContext(context);  // 特别分析:刷新应用程序上下文,比如:初始化默认设置/注入相关Bean/启动 tomcat
  18.             this.afterRefresh(context, applicationArguments);
  19.             stopWatch.stop();
  20.             if (this.logStartupInfo) {
  21.                 (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
  22.             }
  23.             listeners.started(context);
  24.             this.callRunners(context, applicationArguments);
  25.         } catch (Throwable var10) {
  26.             this.handleRunFailure(context, var10, listeners);
  27.             throw new IllegalStateException(var10);
  28.         }
  29.         try {
  30.             listeners.running(context);
  31.             return context;
  32.         } catch (Throwable var9) {
  33.             this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
  34.             throw new IllegalStateException(var9);
  35.         }
  36.     }
复制代码

  • SpringApplication.java : 容器类型很多,会根据你的 this.webApplicationType 创建对应的容器
    默认 this.webApplicationType 是 servlet 也就是 web 容器/处置惩罚的 servlet
  1.     protected ConfigurableApplicationContext createApplicationContext() {
  2.         return this.applicationContextFactory.create(this.webApplicationType);
  3.     }
复制代码

  • ApplicationContextFactory.java
    默认是进入这个分支 case SERVLET:  返回 new AnnotationConfigServletWebServerApplicationContext();
  1. public interface ApplicationContextFactory {
  2.     ApplicationContextFactory DEFAULT = (webApplicationType) -> {
  3.         try {
  4.             switch(webApplicationType) {
  5.             case SERVLET:  // 默认是进入这个分支
  6.                 return new AnnotationConfigServletWebServerApplicationContext();
  7.             case REACTIVE:
  8.                 return new AnnotationConfigReactiveWebServerApplicationContext();
  9.             default:
  10.                 return new AnnotationConfigApplicationContext();
  11.             }
  12.         } catch (Exception var2) {
  13.             throw new IllegalStateException("Unable create a default ApplicationContext instance, you may need a custom ApplicationContextFactory", var2);
  14.         }
  15.     };
  16.     ConfigurableApplicationContext create(WebApplicationType webApplicationType);
  17.     static ApplicationContextFactory ofContextClass(Class<? extends ConfigurableApplicationContext> contextClass) {
  18.         return of(() -> {
  19.             return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
  20.         });
  21.     }
  22.     static ApplicationContextFactory of(Supplier<ConfigurableApplicationContext> supplier) {
  23.         return (webApplicationType) -> {
  24.             return (ConfigurableApplicationContext)supplier.get();
  25.         };
  26.     }
  27. }
复制代码
2.1 实现任务阶段1:创建Tomcat 并启动

  1.     private void refreshContext(ConfigurableApplicationContext context) {
  2.         if (this.registerShutdownHook) {
  3.             shutdownHook.registerApplicationContext(context);
  4.         }
  5.         this.refresh(context);  // 特别分析,真正执行相关任务
  6.     }
复制代码
2.2 实现任务阶段2:创建Spring容器

bean 对象。
  1.     protected void refresh(ConfigurableApplicationContext applicationContext) {
  2.         applicationContext.refresh();
  3.     }
复制代码
bean 对象对应的 config 配置类
  1.     public final void refresh() throws BeansException, IllegalStateException {
  2.         try {
  3.             super.refresh();  // 特别分析这个方法
  4.         } catch (RuntimeException var3) {
  5.             WebServer webServer = this.webServer;
  6.             if (webServer != null) {
  7.                 webServer.stop();
  8.             }
  9.             throw var3;
  10.         }
  11.     }
复制代码
controller 处置惩罚业务哀求的控制器
  1. public void refresh() throws BeansException, IllegalStateException {
  2.         synchronized(this.startupShutdownMonitor) {
  3.             StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
  4.             this.prepareRefresh();
  5.             ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
  6.             this.prepareBeanFactory(beanFactory);
  7.             try {
  8.                 this.postProcessBeanFactory(beanFactory);
  9.                 StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
  10.                 this.invokeBeanFactoryPostProcessors(beanFactory);
  11.                 this.registerBeanPostProcessors(beanFactory);
  12.                 beanPostProcess.end();
  13.                 this.initMessageSource();
  14.                 this.initApplicationEventMulticaster();
  15.                 this.onRefresh();  // 特别分析,当父类完成通用的工作后,再重新动态绑定机制回到
  16.                 this.registerListeners();
  17.                 this.finishBeanFactoryInitialization(beanFactory);
  18.                 this.finishRefresh();
  19.             } catch (BeansException var10) {
  20.                 if (this.logger.isWarnEnabled()) {
  21.                     this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
  22.                 }
  23.                 this.destroyBeans();
  24.                 this.cancelRefresh(var10);
  25.                 throw var10;
  26.             } finally {
  27.                 this.resetCommonCaches();
  28.                 contextRefresh.end();
  29.             }
  30.         }
  31.     }
复制代码
2.3 实现任务阶段3:将Tomcat 和 Spring 容器关联,并启动Spring容器

  1. protected void onRefresh() {
  2.         super.onRefresh();
  3.         try {
  4.             this.createWebServer();  创建 webServer 可以理解成会创建指定 web服务器-tomcat
  5.         } catch (Throwable var2) {
  6.             throw new ApplicationContextException("Unable to start web server", var2);
  7.         }
  8.     }
复制代码
  1. private void createWebServer() {
  2.         WebServer webServer = this.webServer;
  3.         ServletContext servletContext = this.getServletContext();
  4.         if (webServer == null && servletContext == null) {
  5.             StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
  6.             ServletWebServerFactory factory = this.getWebServerFactory();
  7.             createWebServer.tag("factory", factory.getClass().toString());
  8.             this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer
  9. ()}); // 特别分析,使用 TomcatServletWebServerFactory 创建一个TomcatWEbServer
  10.             createWebServer.end();
  11.             this.getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer));
  12.             this.getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer));
  13.         } else if (servletContext != null) {
  14.             try {
  15.                 this.getSelfInitializer().onStartup(servletContext);
  16.             } catch (ServletException var5) {
  17.                 throw new ApplicationContextException("Cannot initialize servlet context", var5);
  18.             }
  19.         }
  20.         this.initPropertySources();
  21.     }
复制代码
3. 末了:

“在这个末了的篇章中,我要表达我对每一位读者的感激之情。你们的关注和复兴是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继承在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表