首页 > 编程知识 正文

springboot源码解析,springbootcms项目

时间:2023-05-03 17:20:27 阅读:42024 作者:573

除了自动组装功能之外,springboot还内置了一个web容器,默认值为tomcat。 在ioc容器启动过程中,web容器启动。 ioc容器的启动带动了web容器的启动。 这也是springboot可以作为jar包启动的原因。 这与以前的war封装方式相反,war封装方式的启动是web容器的启动,牵引了ioc容器的启动。

本文详细介绍了如何在ioc启动时启动tomcat容器的源代码。

首先是入口:

如上一篇文章所述,refresh ) )方法是模板方法,定义了空方法,用户可以重写和扩展这些方法。 onRefresh ) )方法是为子类扩展提供的方法,缺省为空。

springboot中的servletwebserverapplicationcontext重写了onRefresh,cjddn通过添加createWebServer方法启动了web容器。

在createWebServer方法内部,首先创建并返回tomcatervletWebServerFactory,然后调用该getWebServer方法创建Tomcat对象。

此tomcatervletWebServerFactory非常重要,它是一个创建webServer对象并使用它提供web服务的工厂。

首先,详细说明这个对象是从哪里得到的。 这与部署tomcat相关组件有关,也由springboot自动组装机制引入。

META-INF/spring.factories的EnableAutoConfiguration包括嵌入式dedwebserverfactorycustomizerautoconfiguration和seedwebserverferfiguration

servletwebserverfactoryautoconfiguration引入了servletwebserverfactoryconfiguration.embedded tomcat类,而嵌入式Tomcat已引入

根据上一篇文章《springboot自动装配源码详解》,将加载上述类。 此时,这些类的定义信息已经加载,但尚未实例化和初始化。 因为实例化通过finishbeanfactoryinitialization方法进行,而onRefresh在此之前进行。 这意味着在beanDefinitionMap和beanDefinitionNames中已经找到,其中包括名为tomcatServletWebServerFactory的bean。

在中,根据ServletWebServerFactory类型,在beanDefinitionNames中查找时,只有tomcatServletWebServerFactory是ServletWebServerFactory类型

从上图中可以看到,它正在遍历beanDefinitionNames以查找ServletWebServerFactory类型的bean。

我现在获得了一个名为tomcatervletWebServerFactory的beanName。 实例化此bean。

正如我前面所说,此getBean是实例化和初始化bean的位置。 因此,此位置将tomcatServletWebServerFactory实例化为ioc容器。 但是,这里不是简单的实例化和初始化,而是通过BeanPostProcessor向bean添加其他内容

上面的思维导图截图中提到了很多类。 其中几个以Customizer结尾,显然是为了定制。 但是,tomcatservletwebserverfactorybean实例化完成后,在初始化之前将不起作用,因此我们尚未对此进行说明。 那么,我将详细说明它们是如何工作的。

在bean实例化完成和初始化完成之前,将调用所有BeanPostProcessor的前置方法postprocessbeforeinitialization。 其中有webserverfactorycustomizerbeanpostprocessor。 这是为了对这里的tomcatServletWebServerFactory进行其他处理。

其postprocessbeforeinitialization方法首先检索Customizers,即内置容器的定制器。 就是在ioc容器中查找WebServerFactoryC

ustomizer.class 类型的 bean 定义信息。上面提到的几个 Customizers,在这里都能找到。

找到 Customizers 后,就分别调用它们的 customize 方法,来对 tomcatServletWebServerFactory 做定制化。

大概看看这些 Customizers 中做了什么。

里面主要还是设置一些 web 容器的属性。

现在已经知道 tomcatervletWebServerFactory 是怎么获取到的了。然后进 getWebServer 方法里看下。cjddn能看到我们非常熟悉的东西。Service、Connector、Host、Engine 等,这些就是 tomcat 的组件,对应了传统 tomcat 的配置文件中的各种属性。这里只是以 java 对象的方式来实现。最终得到一个 Tomcat 对象。

这里看起来只是创建 Tomcat 对象,那么 tomcat 是在哪里启动的呢。答案是在 getTomcatWebServer 方法中。它返回一个 TomcatWebServer 对象,就是在 TomcatWebServer 的构造方法中,对 tomcat 进行了初始化,初始化时调用了 tomcat 的 start 方法启动 tomat 容器。

tomcat 启动之后,还有一步重要的操作:setDaemonAwaitThread

通过注释也可以看出,所有 tomcat 线程都是后台线程,正常执行完之后就 shutdown 了。

所以为了能让 tomcat 能一直保持运行着,需要创建一个阻塞的,非后台运行的线程来阻止它立即 shutdown!

这个额外的线程,deamon 设置为 false,运行此线程时,tomcat 会一直等待,只要没有一个明确的 shutdown 指令过来,tomcat 就不会停止!

到这边为止,tomcat 容器就算是启动成功了。那么有个疑问,平时我们启动 tomcat 完成后,不是会打印 Tomcat started on port(s): xxxx 吗?这里怎么没有见到呢?

我在 TomcatWebServer 类中,找到了这行注释,

通过在此方法中打上断点,看到了调用链,找到了一个关键的方法:finishRefresh

finishRefresh 也是在 refresh() 方法中的

// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();

它位于 ioc 容器初始化 bean 之后,因为前面虽然 tomcat 已经启动了,但是 ioc 容器还没初始化好恩,要等所有 bean 全部实例化,并初始化好之后,tomcat 才能正式提供服务。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。