看到 spring 的 ServeltContextListener 加载方式时,有个问题。
不知道我的理解对不对:
tomcat 下一个 web 应用目录对应一个 ServeltContext 单例,假设使用 Servelt 处理请求,那一个 Servelt class 其实在 tomcat 容器中也是单例,但是为了提升并发性能,这个单例可能会被多个线程使用。
再到 spring ,在 servlet 被实例化这一步之前, spring 的 ContextLoaderListener 监听器被调用,通过 org.springframework.web.context.ContextLoader 创建 ApplicationContext 对象
问题主要在 ApplicartionContext 这个地方:
这个应用上下文是多线程的吗?因为看到了 static volatile 的 currentContext 和 ConcurrentHashMap 的 currentContextPerThread ,但是为什么还要保存一份当前线程 ContextClassLoader 管理的 WebApplicationContext ?直接用 Heap 区的那一份 currentContext 不行吗?还有,其它线程的 WebApplicationContext 又是在什么时机被创建出来的呢?
1
ihuotui 2017-02-04 23:02:33 +08:00 via iPhone 1
看 web xml 然后看看到底有多少个 context ,看看启动过程。每个 context 的作用。
|
2
yidinghe 2017-02-05 18:12:58 +08:00 1
ServletContext 是一个 Servlet 对象对应的上下文环境,通常 Servlet 是单实例的,因此当你实现一个 Servlet 时,必须保证其线程安全性;至于 ServletContext ,一个 Servlet 对应的 ServletContext 对象也会一直保持在那里,是不会变的。
一般来说,一个 Web 应用会有多个 Servlet ,而它们的 ServletContext 则是共用的一个。这个是由 Servlet 容器(如 Tomcat 、 Jetty )来决定。 ApplicationContext 是 Spring Bean 的上下文环境,它的创建理论上与 ServletContext 无关,但在 SpringMVC 中,这个创建过程自动化了(具体是由 `org.springframework.web.servlet.DispatcherServlet` 触发的),并自动绑定到 ServletContext 下。 ApplicationContext 本身当然是线程安全的,而且里面的 bean (就是你写的那些 Controller 和其他的相关类),缺省情况下也必须是线程安全的。 WebApplicationContext 是 SpringMVC 中对 ApplicationContext 的具体实现,每个 ServletContext 下只会有一个 WebApplicationContext ,在应用初始化时就创建出来了,而不是等浏览器请求来了才创建。 |
3
lml12377 OP @yidinghe 谢谢耐心的回答,还有一个问题请教一下:
假设我的 web.xml 包含这样的配置: <listener> <listener-class>com.xxx.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>business</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> ServletContext 是在 Servlet 之前初始化的: 首先初始化并创建 ServletContext ,接着创建自定义的 ContextLoaderListener.contextInitialized 并把刚刚创建的 ServletContext 传递给它,看代码 WebApplicationContext 应该是在 ContextLoader.initWebApplicationContext 里创建出来的;接着才是 DispatcherServlet 的创建。 你上面说的 [这个创建过程自动化了(具体是由 `org.springframework.web.servlet.DispatcherServlet` 触发的)],是不是指的是当我不指定 ContextLoaderListener 的情况? |
4
yidinghe 2017-02-07 11:28:54 +08:00 1
可能我描述有不准确的地方。以代码为准就是了。
|