在WebApplicationInitializer中加载ApplicationContexts的层次结构

时间:2012-10-20 01:08:55

标签: java spring spring-mvc servlet-3.0

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

在我见过的常见示例中,您有一个Root ApplicationContext,加载了ContextLoaderListener,以及一个加载了DispatcherServlet的servlet ApplicationContext。

(很明显,我不是在谈论web.xml,而是以编程方式,在We​​bApplicationInitializer中)。

现在,我希望有一个ApplicationContexts层次结构,让我们说:

Root - > AppContext1 - > AppContext2 - > ServletAppContext

- > 表示家长 - >孩子的关系。每个AppContext都可以访问自己的bean及其祖先。

举个例子:

  • Root定义属性,DAO和TX。
  • AppContext1定义了JPA和Spring Data存储库。
  • 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个ContextLoaderListeners,每个AppContexts(Root,1,2)都有1个。

我的问题是,这种情况的正确方法是什么?我愿意接受建议。

2 个答案:

答案 0 :(得分:1)

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

如果它是线性关系(即,每个上下文只有一个子节点),那么您可以使用扩展的ApplicationContext实现,其close方法也调用父关闭。

如果它不是线性关系 - 那么你可以实现一个引用计数机制来跟踪有多少活动子上下文,当它达到0时关闭上下文。

在做这些之前,你应该强烈重新考虑有这么多背景的原因。最好只创建两个上下文并使用导入来连接配置文件。我看起来像是工程师。我不能想到做这样的事情的好用例,会非常有兴趣听到你为什么这样做。

答案 1 :(得分:0)

所以,显然我正在尝试做一些事情(至少达到版本3.1)不准备做。