[英]Spring: Loading PropertyPlaceholderConfigurer
Here is the situation: 情况如下:
The xml configuration looks as follows: xml配置如下所示:
<bean id="ppConfig1"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:c:\test\env.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
<bean id="string" class="java.lang.String" depends-on="ppConfig1">
<constructor-arg value="${env.app.type}"/>
</bean>
<bean id="ppConfig2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
<property name="locations">
<list>
<value>file:c:\test\#{string}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
</bean>
As is evident, I want load a specific property file (eg app1.properties) based on the value of key env.app.type
in C:\\test\\env.properties
. 显而易见,我想基于
C:\\test\\env.properties
的键env.app.type
的值加载特定的属性文件(例如app1.properties)。
The code to load/test the above config looks as follows: 加载/测试上述配置的代码如下:
ApplicationContext context = new ClassPathXmlApplicationContext(
"SpringBeans.xml");
String ss = (String)context.getBean("string");
System.out.println(ss);
This seems not working. 这似乎不起作用。 It failing with following error:
失败并显示以下错误:
Exception in thread "main" org.springframework.beans.factory.BeanInitializationException: Could not load properties;
线程“主”中的异常org.springframework.beans.factory.BeanInitializationException:无法加载属性。 nested exception is java.io.FileNotFoundException: C:\\test\\${env.app.type}.properties (The system cannot find the file specified) at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)
嵌套的异常是java.io.FileNotFoundException:C:\\ test \\ $ {env.app.type} .properties(系统找不到指定的文件),位于org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer。的java:87)
The file c:\\test\\env.properties
looks as follows 文件
c:\\test\\env.properties
如下所示
env.app.type=app1
env.app.type = APP1
One interesting observation is that when I comment out the ppConfig2
, everything works fine and correct value of env.app.type
is printed. 一项有趣的观察是,当我注释掉
ppConfig2
,一切正常,并显示了env.app.type
正确值。 I am open to any other suggestion to get around this. 我愿意接受任何其他建议来解决此问题。 My basic requirement is to select the property file at run time based on the property specified in env.properties.
我的基本要求是在运行时根据env.properties中指定的属性选择属性文件。 (I am using spring 3.1.0)
(我正在使用spring 3.1.0)
You need something like this: 您需要这样的东西:
<context:component-scan base-package="com.foo.bar" />
<context:property-placeholder location="file:c:/test/${env.app.type}.properties" />
<bean id="service" class="com.foo.bar.ExampleService">
<property name="foo" value="${foo}" />
</bean>
package com.foo.bar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("file:c:/test/env.properties")
public class SpringConfig{
}
And "foo" value comes from app1.properties
file. 而“ foo”值来自
app1.properties
文件。 Basically, one file is being loaded with @PropertySource
, the other with the regular property placeholder. 基本上,一个文件是使用
@PropertySource
加载的,另一个文件是使用常规属性占位符加载的。
I think you are trying to do things that Spring does not like. 我认为您正在尝试做Spring不喜欢的事情。 The normal order for bean initialization is :
Bean初始化的正常顺序为:
As long as those 3 passes are cleanly separated, all will be ok, but you have a post processor bean ( ppConfig2
) depending on a simple bean ( string
). 只要将这3个遍完全分开,就可以了,但是您有一个后处理器bean(
ppConfig2
),具体取决于一个简单的bean( string
)。
IMHO, you should avoid such construct if possible. 恕我直言,如果可能,您应该避免这种构造。 Even if it works now, you are under the risk of problem arising at any modification of you application context because you are allready on the edge.
即使现在可以使用,您也有可能在对应用程序上下文进行任何修改时出现问题,因为您已经准备就绪。
Could it be acceptable to use environment variables or system properties to avoid that a bean post-processor depends on another bean post-processor ? 使用环境变量或系统属性来避免bean后处理器依赖于另一个bean后处理器是否可以接受? If yes, you would'nt be bothered by
ppConfig1
and simply have : 如果是的话,您将不会被
ppConfig1
所困扰,只需拥有:
<bean id="ppConfig2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
<property name="locations">
<list>
<value>file:c:\test\${configured_env}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
</bean>
If environment variables or system properties are not an option, you could use programmatic configuration as suggested by Andrei Stefan. 如果不能选择环境变量或系统属性,则可以使用Andrei Stefan建议的编程配置。
You can do this with util:properties
: 您可以使用
util:properties
做到这一点:
<util:properties id="envProperties" location="env.properties"/>
<util:properties id="properties" location="#{envProperties.getProperty('env.app.type')}.properties"/>
<context:property-placeholder properties-ref="envProperties" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder properties-ref="properties" ignore-unresolvable="true"/>
BTW there's a bug in Spring that prevents Spring EL from being evaluated inside location
attribute in context:property-placeholder
. 顺便说一句,Spring中有一个错误 ,阻止Spring EL在
context:property-placeholder
location
属性内进行评估。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.