我需要更改基于属性使用的spring applicationContext.xml文件,此属性必须在war文件之外的某处定义(即,它不能在web.xml中)。目前,我已经得到了以下解决方案(请参阅下面的答案),想知道是否有更好的方法可以做到这一点?
答案 0 :(得分:2)
我的解决方案有4个部分。首先,在我的应用程序的web.xml中,我定义了以下内容:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation1</param-name>
<param-value>classpath:applicationContext-1.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation2</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>com.my.package.MyContextLoaderListener</listener-class>
</listener>
然后我扩展ContextLoaderListener
package com.my.package;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.ContextLoaderListener;
public class MyContextLoaderListener extends ContextLoaderListener {
@Override
protected ContextLoader createContextLoader() {
return new MyContextLoader();
}
}
和ContextLoader
package com.my.package;
import javax.servlet.ServletContext;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ContextLoader;
public class LnvContextLoader extends ContextLoader {
private static final String APP_CONTEXT_PROP = "MY_CONTEXT_LOAD_PARAM";
@Override
protected void customizeContext(ServletContext servletContext,
ConfigurableWebApplicationContext wac) {
//check for system property first, if not defined, check for env variable
String appContextParam = System.getProperty(APP_CONTEXT_PROP);
if(appContextParam==null)
{
appContextParam = System.getenv(APP_CONTEXT_PROP);
}
if(appContextParam!=null && !appContextParam.equals("")){
String initParam = servletContext.getInitParameter(appContextParam);
wac.setConfigLocation(initParam);
}
}
}
最后,在我的tomcat启动中,我在setenv.bat
中定义了环境变量set MY_CONTEXT_LOAD_PARAM=contextConfigLocation1
此解决方案从环境变量加载它,但代码很灵活,允许在系统属性中设置它。
答案 1 :(得分:2)
您是否考虑过使用beanRefContext方法。 (ContextSingletonBeanFactoryLocator的)。这样,您可以通过另一个spring配置文件配置spring配置文件(及其名称)。
然后,您可以通过您认为合适的任何方式对该文件进行参数化,并以此方式切换文件名。
该文件如下所示:
<beans>
<bean id="businessBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="${NameOfBeanConfigFile}" />
</bean>
</beans>
您可以使用PropertyPlaceHolderConfigurer设置NameOfBeanConfigFile的值。
我喜欢这种方法,因为这意味着我可以将静态bean配置文件名与动态bean配置文件名混合,因此不必复制bean配置。
当我不得不做类似的事情时,我会通过作为URL资源加载的配置文件进行参数化(通过jndi)
答案 2 :(得分:-2)
如果通过类路径加载应用程序上下文,则可以通过在服务器的类路径中放置另一个版本的applicationContext.xml来覆盖它。
我的解决方案是拥有一个非常简单的applicationContext,其中包含真正的应用程序上下文:
applicationContext.xml:
<beans>
<import resource="classpath:realContext.xml"/>
</beans>
如果您需要其他上下文,请使用以下命令将applicationContext.xml添加到服务器的类路径中:
<beans>
<import resource="classpath:realContext2.xml"/>
</beans>
并在WAR中打包realContext.xml和realContext2.xml。不需要花哨的上下文监听器。
只是我的意见,但我完全不喜欢拥有非自包含的WAR。我发现拥有一个部署单位非常方便。所以我更愿意在构建过程中创建两个不同版本的WAR,每个版本都需要一个配置。
另一种解决方案是,如果要根据给定属性加载不同的bean,可以使用PropertyPlaceholderConfigurer并将bean的名称作为属性:
<beans>
<bean id="bean1" .../>
<bean id="bean2" .../>
<bean id="otherBean">
<property name="injectDifferentBean" ref="${property.containing.bean.name" />
</bean>
</beans>
和一个属性文件:
property.containing.bean.name=bean1
或
property.containing.bean.name=bean2