如何声明父应用程序上下文

时间:2010-11-30 19:31:21

标签: spring

我发现自己在applicationContext.xml和applicationContext-test.xml中使用了两个相同的bean。我希望我的测试上下文能够从我的应用程序上下文继承,以避免重复我自己。

我已经看到很多材料表明您可以从该上下文声明父应用程序上下文和引用bean,但我找不到有用的示例。有人可以帮忙吗?

更新 作为一些背景信息,我的正常应用程序上下文正在web.xml中加载:

<context-param>
    <description>Application Contexts for Spring</description>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> 

我的测试应用程序上下文在我的单元测试中加载:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext-test.xml")

因此,假设我在常规环境中有一个bean:

<bean name="someBean" class="com.foo.MyClass" />

然后,在我的测试应用程序上下文中,我想引用这个bean。我该怎么做?

更新

根据skaffman的建议,我已将bean移动到SharedBeans.xml文件中并将其导入到我的applicationContext.xml中。但是,这会导致SAXParser异常:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:SharedBeans.xml]
Offending resource: ServletContext resource [/WEB-INF/classes/applicationContext.xml]; nested exception is org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 1 in XML document from class path resource [SharedBeans.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'bean'.
    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)

我无法确定我做错了什么。 bean在我的上下文文件中工作正常,我所做的就是剪切并粘贴到新文件中。以下是SharedBeans.xml的完整内容:

<bean name="properties" class="com.foo.Properties">
    <constructor-arg><value>${module.name}</value></constructor-arg>
    <constructor-arg><value>${businessUnit}</value></constructor-arg>
    <constructor-arg><value>${product}</value></constructor-arg>
    <constructor-arg><value>${env}</value></constructor-arg>
    <constructor-arg><value>${machineName}</value></constructor-arg>
    <constructor-arg><value>${collectionSet.company}</value></constructor-arg>
    <constructor-arg><value>${route.tag}</value></constructor-arg>
    <constructor-arg><value>${timeout}</value></constructor-arg>      
</bean>

2 个答案:

答案 0 :(得分:5)

对于父上下文来说,这并不是一个特别好的用例,它主要用于设置层次结构(例如一个根we​​bapp上下文,多个子servlet上下文)。

对于您的情况,如果您只是将公共bean定义提取到一个单独的文件中,然后<import>将它们放入需要它的每个上下文文件中,它将变得更简单,更容易理解。你可以用父子情境来做这件事,但是这样做会更难理解,不必要的。

好的,举个例子,将您的共享bean定义放入名为shared-beans.xml的文件中,并将其(现在)放在类路径的顶层,包含:

<bean name="someBean" class="com.foo.MyClass" />

然后,在applicationContext-test.xml/WEB-INF/classes/applicationContext.xml内添加以下内容:

<import resource="classpath:/shared-beans.xml" />

shared-beans.xml中的所有bean定义现在都将导入到每个应用程序上下文中。通过执行此操作,您无法获得第三个应用程序上下文,只需从另一个文件中导入bean定义。

答案 1 :(得分:0)

您可以将公共声明移动到单独的XML文件中,并将其放在类路径中(以便从测试中轻松访问)。然后,您可以执行以下操作:

<context-param> 
    <description>Application Contexts for Spring</description> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>
        /WEB-INF/classes/applicationContext.xml
        classpath:/common-beans.xml
    </param-value> 
</context-param> 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(
    locations = {"/applicationContext-test.xml", "common-beans.xml"}) 

根据skaffman的建议,您还可以使用common-beans.xml从两个上下文中添加<import>