如何让 class 知道 Spring MVC 中的多个应用程序上下文?
How to make a class aware of multiple application contexts in Spring MVC?
我正在尝试理解 Spring MVC 中应用程序上下文的概念。为了检查它,我创建了一个具有两个应用程序上下文 Test-application-context1.xml
和 Test-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 应用程序上下文,但是如果我说重命名testObject
到 testObject1
在 '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)。
我正在尝试理解 Spring MVC 中应用程序上下文的概念。为了检查它,我创建了一个具有两个应用程序上下文 Test-application-context1.xml
和 Test-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 应用程序上下文,但是如果我说重命名testObject
到 testObject1
在 '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
导入后,您的示例将抛出 NoUniqueBeanDefinitionException,因为您有超过 1 个 bean 相同 相同 应用程序上下文中的名称 (testObject)。