我正在使用Servlet 3(Tomcat 7)+ Spring 3.1,并尝试使用WebApplicationInitializer加载我的Web应用程序。

在我见过的通常示例中,您有一个Root ApplicationContext(已加载ContextLoaderListener)和一个Servlet ApplicationContext(已加载DispatcherServlet)。

(要清楚,我不是在谈论web.xml,而是在WebApplicationInitializer内部以编程方式谈论)。

现在,我想拥有一个ApplicationContexts的层次结构,假设:

根-> AppContext1-> AppContext2-> ServletAppContext

->表示父级->子级关系。每个AppContext都可以访问其自己的bean和其祖先的bean。

例如:


根定义属性DAO和TX。
AppContext1定义了JPA和Spring数据存储库。
AppContext2定义了JMS和Spring集成管道。
ServletAppContext定义了控制器和视图。


我的第一种方法是将Root ApplicationContext添加到ContextLoaderListener,然后将其设置为AppContext1的父级。将AppContext1设置为AppContext2的父级。将AppContext2设置为ServletAppContext的父级。最后,将ServletAppContext与DispatcherServlet关联。

问题是,在关闭时,DispatcherServlet关闭ServletAppContext,但不会传播。 AppContext1和AppContext2永远不会对它们的bean不开放。所以我猜我使用了错误的方法。

我尝试将AppContext2关联到ContextLoaderListener而不是Root。在这种情况下,AppContext2关闭,但AppContext1和Root保持打开状态。

我也不能拥有3个ContextLoaderListener,每个AppContext(Root,1、2)都需要1个。

我的问题是,对于这种情况,正确的方法是什么?我愿意提出建议。

最佳答案

不关闭父上下文的默认行为是因为多个子上下文可以共享一个父上下文。在这种情况下,只有在所有子上下文都关闭后才能关闭父上下文。

如果是线性关系(即每个上下文只有一个子代),则可以使用扩展的ApplicationContext实现,该实现的close方法也调用父close。

如果不是线性关系,则可以实现引用计数机制,以跟踪存在的活动子上下文(当达到0时,关闭上下文)。

在执行任何此操作之前,您应该强烈地重新考虑具有这么多上下文的原因。只创建两个上下文并使用导入来连接配置文件可能会更好。对我来说,我看起来像是在做工程。我想不出做这样的事情的好用例,对听到为什么这样做很感兴趣。

07-26 04:25