作者回复: Tomcat&Jetty在启动时给每个Web应用创建一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring容器提供宿主环境。
Tomcat&Jetty在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听到这个事件,它的contextInitialized方法会被调用,在这个方法中,Spring会初始化全局的Spring根容器,这个就是Spring的IoC容器,IoC容器初始化完毕后,Spring将其存储到ServletContext中,便于以后来获取。
Tomcat&Jetty在启动过程中还会扫描Servlet,一个Web应用中的Servlet可以有多个,以SpringMVC中的DispatcherServlet为例,这个Servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet请求。
Servlet一般会延迟加载,当第一个请求达到时,Tomcat&Jetty发现DispatcherServlet还没有被实例化,就调用DispatcherServlet的init方法,DispatcherServlet在初始化的时候会建立自己的容器,叫做SpringMVC 容器,用来持有Spring MVC相关的Bean。同时,Spring MVC还会通过ServletContext拿到Spring根容器,并将Spring根容器设为SpringMVC容器的父容器,请注意,Spring MVC容器可以访问父容器中的Bean,但是父容器不能访问子容器的Bean, 也就是说Spring根容器不能访问SpringMVC容器里的Bean。说的通俗点就是,在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。
作者回复: Filter是Servlet规范的一部分,是Servlet容器Tomcat实现的。Intercepter是Spring发明的。它们的执行顺序是:
Filter.doFilter();
HandlerInterceptor.preHandle();
Controller
HandlerInterceptor.postHandle();
DispatcherServlet 渲染视图
HandlerInterceptor.afterCompletion();
Filter.doFilter(); Servlet方法返回
作者回复: DispatcherServlet中的成员变量都是初始化好后就不会被改变了,所以是线程安全的,那“可见性”怎么保证呢?
这是由Web容器比如Tomcat来做到的,Tomcat在调用Servlet的init方法时,用了synchronized。
private synchronized void initServlet(Servlet servlet)
{...}
作者回复: 本来想自己画一张,但是在网上找了一下,找到这张图,蛮清楚的:
https://blog.csdn.net/zhanglf02/article/details/89791797
作者回复: 对的,说的很好
作者回复: 不太准确哦,首先我们明确一点,Spring和SpringMVC分别有自己的IOC容器或者说上下文。
为什么要分成两个容器呢?为了职责划分清晰。
SpringMVC的容器直接管理跟DispatcherServlet相关的Bean,也就是Controller,ViewResolver等,并且SpringMVC容器是在DispacherServlet的init方法里创建的。而Spring容器管理其他的Bean比如Service和DAO。
并且SpringMVC容器是Spring容器的子容器,所谓的父子关系意味着什么呢,就是你通过子容器去拿某个Bean时,子容器先在自己管理的Bean中去找这个Bean,如果找不到再到父容器中找。但是父容器不能到子容器中去找某个Bean。
其实这个套路跟JVM的类加载器设计有点像,不同的类加载器也为了隔离,不过加载顺序是反的,子加载器总是先委托父加载器去加载某个类,加载不到再自己来加载。
作者回复: 我理解你说的Servlet容器应该是说HTTP服务器+Servlet容器,Servlet容器本身只管Servlet的事,不管HTTP协议的解析
作者回复: 对的
作者回复: 方便责任链模式下层层传递
作者回复: 😑,谢谢
作者回复: 就是处理网络通信,接收到HTTP请求后,把HTTP请求数据转成标准的ServletRequest对象,再把这个对象交给Servlet容器去处理
作者回复: SpringBoot中只有一个Spring上下文:
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
你可以在FrameworkServlet.initWebApplicationContext方法中下个断点。
作者回复: 完全理解,你可以把Tomcat和Jetty本身当成一个项目,源码跑起来,再结合专栏的讲解,理解Java技术该怎么用
作者回复: 将全局的Spring容器做为ServletContext的一个属性,代码在ContextLoader类中的initWebApplicationContext方法:
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ServletContext就是用来共享数据的,比如SpringMVC需要从ServletContext拿到全局的Spring容器,把它设置成自己的父容器。
作者回复: 你可以把HTTP服务器理解为Tomcat的一部分。