Java 在WebApplicationInitializer中加载ApplicationContexts的层次结构

Java 在WebApplicationInitializer中加载ApplicationContexts的层次结构,java,spring,spring-mvc,servlet-3.0,Java,Spring,Spring Mvc,Servlet 3.0,我正在使用Servlet3(Tomcat7)+Spring3.1,并尝试使用WebApplicationInitializer加载我的webapp 在我看到的常见示例中,您有一个根ApplicationContext,用ContextLoaderListener加载,还有一个servlet ApplicationContext,用DispatcherServlet加载 (明确地说,我不是在谈论web.xml,而是在WebApplicationInitializer中以编程的方式谈论它) 现在,我

我正在使用Servlet3(Tomcat7)+Spring3.1,并尝试使用WebApplicationInitializer加载我的webapp

在我看到的常见示例中,您有一个根ApplicationContext,用ContextLoaderListener加载,还有一个servlet ApplicationContext,用DispatcherServlet加载

(明确地说,我不是在谈论web.xml,而是在WebApplicationInitializer中以编程的方式谈论它)

现在,我想要一个ApplicationContexts的层次结构,比如说:

Root->AppContext1->AppContext2->ServletAppContext

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

例如:

  • 根定义属性、DAO和TX
  • AppContext1定义了JPA和Spring数据存储库
  • AppContext2定义了JMS和Spring集成管道
  • ServletAppContext定义控制器和视图
我的第一种方法是将根ApplicationContext添加到ContextLoaderListener,然后将其设置为AppContext1的父级。将AppContext1设置为AppContext2的父级。将AppContext2设置为ServletAppContext的父级。最后将ServletAppContext与DispatcherServlet关联

问题是,在关机时,DispatcherServlet关闭ServletAppContext,但它不会传播。AppContext1和AppContext2永远不会关闭,它们的bean永远不会发布。所以我猜我用了一个错误的方法

我尝试将AppContext2与ContextLoaderListener而不是根关联。在本例中,AppContext2关闭,但AppContext1和Root保持打开状态

我也不能有3个ContextLoaderListener,每个AppContext(根,1,2)1个


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

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

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

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


在做这些之前,你应该强烈地重新考虑有这么多上下文的原因。最好只创建两个上下文并使用导入来连接配置文件。我看起来像是过度工程化了。我想不出一个好的用例来做这样的事情,我很想听听你为什么这么做

很明显,我正在尝试做Spring(至少在3.1版之前)不准备做的事情。

只是出于好奇,为什么首先需要这么复杂的方案。这个想法是为了更好地实现bean的模块化(我认为这应该是一个很好的实践)。我不认为这应该很复杂,当然,您不能使用web.xml来实现这一点,所以这是一种新的方法。作为奖励,它最小化了不符合后期处理条件的bean,请参见我上面的评论以获得解释