我的一位同事和我正在玩下面的弹簧配置:
<beans>
<context:property-placeholder location='classpath:/configuration.properties'/>
<bean id="myBean" class="${type}" />
</beans>
我们希望能够提供myBean
的特定于环境的实现。在开发人员系统上,type
的值将是myBean
所做的轻量级实现。在生产环境中,我们将使用完整版本。
当我的同事运行代码时,一切正常。当我运行代码时,我得到一个ClassNotFoundException
,因为spring试图实例化${type}.class
。而且它有时不起作用,有时却不起作用。在我的机器上它总是失败,在我的同事机器上它始终有效。
有人知道问题是什么吗?
提前, 选手Yevgeniy
更新
根据要求,以下是我们加载应用程序上下文的方式:
ClassPathXmlApplicationContext("application-configuration.xml");
属性文件的内容非常简单:
type=foobar.TestServiceImpl
答案 0 :(得分:1)
我没有尝试使用占位符覆盖类,而是想为您的问题建议一种替代方法。您可以使用Spring的Profile功能。
根据环境改变班级会更简单,更安全。
<beans>
<beans profile="dev">
<bean id="myBean" class="dev.impl.MyBean" />
</beans
<beans profile="prod">
<bean id="myBean" class="prod.impl.MyBean" />
</beans
</beans>
然后,您可以通过将以下系统属性添加到服务器-Dspring.profiles.active="dev"
来激活开发中的给定配置文件。
您可以通过将以下内容添加到web.xml
:
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>prod</param-value>
</context-param>
答案 1 :(得分:1)
以下假设是Spring 3.1 +。
我可以肯定地告诉你。对于Spring而言,ClassNotFoundException
为类
${type}
表示它没有解析占位符。
指定
时<context:property-placeholder location='classpath:/configuration.properties'/>
Spring使用PropertyPlaceholderBeanDefinitionParser
注册将执行占位符解析的PropertySourcesPlaceholderConfigurer
或PropertyPlaceholderConfigurer
bean。
PropertySourcesPlaceholderConfigurer
是BeanFactoryPostProcessor
。这意味着它可以修改bean定义。如果没有详细说明,如果它无法解析占位符,则该过程将失败并显示IllegalArgumentException
,表明占位符无法解析。
如果您说${type}
未解决,则表示未创建PropertySourcesPlaceholderConfigurer
或PropertyPlaceholderConfigurer
个bean。这可能意味着您的上下文没有
<context:property-placeholder location='classpath:/configuration.properties'/>
根据您向我们展示的信息,我认为这是正在发生的事情。如果你能证明不是这样,我会请你提供一个可重复的小例子。理想情况下,您将显示已编译项目的内容。
答案 2 :(得分:0)
据我记得,物业占位符相互失败。这意味着如果它无法在您的计算机上找到文件configuration.properties
,则该属性不会被初始化。
要批准此假设,请尝试“破坏”同事计算机上的应用程序:将位置更改为错误,例如classpath:/configuration12345.properties
。我相信这个问题也会出现在他的机器上。
现在,检查您的环境中出了什么问题,以及为什么在那里找不到此文件。
但是:你对配置文件有什么看法吗? Spring提供了一个很酷的功能,完全符合您的用例:spring profiles。