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

How to make a class aware of multiple application contexts in Spring MVC?

我正在尝试理解 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>

现在我想在我的一个控制器 class 中注入这些 application/web 应用程序上下文。我不确定如何正确地针对多个上下文执行此操作。我知道当我有一个上下文时我可以让我的 class 实现 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());
    }
}

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

1) 当我们使 class 实现具有多个上下文的 ApplicationContextAware 时,哪个上下文将被注入到那个 class?它是被注入的一个上下文还是 spring 以某种方式组合所有上下文并将它们作为一个 applicationContext 对象注入(这可以解释为什么当我在一个中更改 bean 的名称时我从不同的上下文中获取值上下文)?

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

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

回答你的第二个问题,

使用 @ImportResource 如下。

来自docs,

Like @Import, this annotation provides functionality similar to the element in Spring XML. It is typically used when designing @Configuration classes

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

这将从 both 应用程序上下文加载 all beans 到 class ConfigClass。

更新:

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

您可以使用 @Autowired

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

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