如何使类知道Spring MVC中的多个应用程序上下文?

时间:2017-02-03 16:21:35

标签: spring spring-mvc dependency-injection applicationcontext

我正在尝试理解Spring MVC中应用程序上下文的概念。为了检查它,我创建了一个包含两个应用程序上下文Test-application-context1.xmlTest-application-context2.xml以及一个Web应用程序上下文Test-dispatcher-servlet.xml的应用程序。在所有这些上下文中,我初始化了一个带有两个字段的简单java bean:

1)在Test-application-context1.xml

<bean id="testObject" class="test.TestObject">
    <property name="fName" value="FirstName Context1"/>
    <property name="lName" value="LastName Context1"/>
</bean> 

2)在Test-application-context2.xml

<bean id="testObject" class="test.TestObject">
    <property name="fName" value="FirstName Context2"/>
    <property name="lName" value="LastName Context2"/>
</bean> 

3)在Test-dispatcher-servlet.xml ::

<bean id="testObject" class="test.TestObject">
    <property name="fName" value="FirstName WebContext"/>
    <property name="lName" value="LastName WebContext"/>
</bean> 

我还在web.xml文件中提供了一个正确的配置,以便在服务器启动时初始化所有这些上下文:

 <servlet>
    <servlet-name>dispatcherTest</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/Test-dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherTest</servlet-name>
    <url-pattern>/Test/*</url-pattern>
</servlet-mapping>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/Test-application-context1.xml /WEB-INF/Test-application-context2.xml</param-value>
</context-param>

现在我想在我的一个控制器类中注入这些应用程序/ Web应用程序上下文。我不确定如何正确地为多个上下文执行此操作。我知道当我有一个上下文时,我可以使我的类实现ApplicationContextAware所以我尝试了这样:

@Controller
public class TestController implements ApplicationContextAware{

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
}

@RequestMapping(value = "/Test")
public void Test(HttpServletRequest request) {
    TestObject testObject = applicationContext.getBean("testObject", TestObject.class);
    System.out.println("fName="+testObject.getfName()+"; lName="+testObject.getlName());
    }
}

在上面的示例中,我始终从testObject获取Test-dispatcher-servlet.xml的值,因此,此处注入的applicationContext似乎表示Web应用程序上下文,但如果我说重命名{{ 1}}到{Test-dispatcher-servlet.xml'中的testObject并运行相同的代码,我将从testObject1获取值,所以这里是我的问题。

1)当我们创建具有多个上下文的类实现Test-application-context2.xml时,哪个上下文将被注入该类?是一个正在注入的上下文,还是以某种方式组合所有上下文并将它们作为一个applicationContext对象注入(这可以解释为什么我在其中一个上下文中更改bean的名称时从不同的上下文中获取值) ?

2)将多个应用程序上下文注入类中的正确方法是什么?

我知道上面的例子不是一个典型的场景,可能是一个糟糕的设计模式,但我只是想了解整个事情的运作方式。

1 个答案:

答案 0 :(得分:1)

回答你的第二个问题,

使用 @ImportResource ,如下所示。

来自docs

  

与@Import一样,此注释提供类似于的功能    Spring XML中的元素。它通常在设计时使用   @Configuration classes

@Configuration  
@ImportResource( { "Test-application-context1.xml", "Test-application-context2.xml" } )  
public class ConfigClass { } 

这会将所有应用程序上下文中的所有 bean加载到类ConfigClass中。

<强>更新

因此,导入后将存在仅存在一个应用程序上下文。

您可以使用@Autowired

从任何导入的* .context.xml访问任何 bean

导入后,您的示例将抛出NoUniqueBeanDefinitionException,因为您在中有超过1个带有相同名称(testObject)的bean相同的应用程序上下文。