文章目录
- 前言
- Tomcat关键流程
- 1. 引导程序
- 2. 实例化`Catalina`容器
- 3. 创建server, service
- 4. 创建Engine,Connector
- 5. 启动
- 6. 创建StandardContext(Tomcat上下文)
- 7. 解析web.xml并加载
- 8. 调用SpringMvc的应用初始化程序
- 9. 初始化spring容器
- 10. 初始化servlet容器
前言
本篇没有营养,只是记录的Tomcat的启动的一个过程,非常粗略,目的是为了了解,Tomcat是怎么加载SpringMvc并启动SpringMvc的,基本上只记录了关键位置,比如创建关键对象、加载配置、及通知应用的方式等等。
后续考虑深入研究下。
Tomcat关键流程
水平有限,简单的对Tomcat启动及应应用的启动做了一个简单的说明,没什么技术含量,单纯的想知道Tomcat是怎么启动应用的。
1. 引导程序
位置: org.apache.catalina.startup.Bootstrap#main
2. 实例化Catalina
容器
这里初始化类加载,然后反射调用setParentClassLoader(URLClassloader)
之后command=“start” 表示启动,之后调用load()方法,进行调用Catalina.load() 方法
3. 创建server, service
之后会进入到:org.apache.catalina.startup.Catalina#load()
这里初始化了一些东西,解析并加载了server.xml,
这里的server.xml 解析后是StandardServer(实现Server接口)对象,这里我们将它看做Tomcat容器(并不是web服务容器)
可以查看server.xml,它有几个标签
代码语言:javascript复制<server>
<service>
<Connector></Connector>
<Engine></Engine>
<Host></Host>
<Realm></Realm>
</service>
</server>
在获取到server对象后,它随即将Catalina设置进去了,Catalina是servlet容器,
然后在初始了日志输出,
4. 创建Engine,Connector
最后调用getServer().init() 方法,init()是StandardServer的父类LifecycleBase
默认实现的,如下:
他会逐步的调用子容器的init
最后在StandardService里engine.init(), connector.init()
走到这里,它创建了Engine对象,和connector对象,此时engine和connector都是StandardServer的属性
5. 启动
位置:org.apache.catalina.core.StandardServer#startInternal
6. 创建StandardContext(Tomcat上下文)
StandardContext 是为也可以看做Tomcat上下文对象,很多操作都有它处理,用于处理请求、加载、初始化等操作,它就提供了获取servlet上下文对象(servletContext)的方法,还可以设置应用监听器、读取web.xml、设置编码等操作。
位置:org.apache.catalina.startup.Bootstrap#main
daemon.load 上面第六步前的过程,它创建容器server -> service (Engine connector)
到这一步,它是反射执行Catalina.start()方法
然后一步步的去调用内部子容器的start()方法
在调用engine.start()
org.apache.catalina.mbeans.MBeanFactory#createStandardContext(java.lang.String, java.lang.String, java.lang.String, boolean, boolean)
7. 解析web.xml并加载
org.apache.catalina.startup.ContextConfig#webConfig
它先是加载了应用的web.xml,然后将Tomcat的web.xml进行merge
然后将web.xml的配置都加到ServletContext
中:org.apache.catalina.startup.ContextConfig#configureContext
然后再将调用外部方法通知的类加入到servletContext
8. 调用SpringMvc的应用初始化程序
位置:org.apache.catalina.core.StandardContext#startInternal
然后调用外部通知方法
它这里是entry.getKey().onStartup
,它的是org.springframework.web.SpringServletContainerInitializer
然后这里就到了springMvc的org.springframework.web.SpringServletContainerInitializer#onStartup
可是,这里Tomcat给它传了4个抽象类,根据注释这个方法是提供给我们做其他web应用程序初始化的方法,感觉是我们也可以做类似Tomcat的web服务器,将其他web应用进行扫描然后读取到这4个抽象类实现的类进行上下文传递
9. 初始化spring容器
上面执行应用初始化程序,没有进行初始化,但是在这一步,就会走我们在web.xml配置的类ContextLoaderListener
,然后初始化spring容器。
监听器在解析web.xml时就已经添加,所以这里只要执行就行
代码语言:javascript复制 <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
10. 初始化servlet容器
最后会执行子容器的启动
位置:
org.springframework.web.servlet.FrameworkServlet#initServletBean