带有注释的 Spring 4 PropertyPlaceholder
Posted
技术标签:
【中文标题】带有注释的 Spring 4 PropertyPlaceholder【英文标题】:Spring 4 PropertyPlaceholder with Annotations 【发布时间】:2014-05-09 20:29:56 【问题描述】:好的,我知道这个问题已经被问过好几次了,我已经尝试了他们建议的答案中的每一个解决方案,但还没有找到一个有效的解决方案,所以我希望这里的人能指出我正确的方向。
我正在尝试将 Spring 4 与以 Java 为中心的配置一起使用,但在从属性文件加载属性时遇到问题。我的最新方法几乎是逐字遵循 Spring 的文档 here,但即使这样也行不通。
这是我的 properties-config.xml 文件(位于我的类路径上的 /config 目录中):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:property-placeholder location="classpath:db.properties"/>
</beans>
这是我的网络应用初始化程序类(一个 sn-p,无论如何):
public class TestWebAppInitializer implements WebApplicationInitializer
@Override
public void onStartup(ServletContext container)
// Instantiate a new web application context
AnnotationConfigWebApplicationContext appContext =
new AnnotationConfigWebApplicationContext();
// Load the configurations
appContext.scan("com.acme.config");
appContext.refresh();
// Add the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
// Add the various listeners
container.addListener(new ContextLoaderListener(appContext));
container.addListener(new RequestContextListener());
最后是一个使用属性文件的小示例配置类:
package com.acme.config;
@Configuration
@ImportResource("classpath:config/properties-config.xml")
public class HibernateConfiguration
@Value("$jdbc.url")
private String jdbcUrl;
@Value("$jdbc.username")
private String jdbcUsername;
@Value("$jdbc.password")
private String jdbcPassword;
@Bean(name = "dataSource")
public ComboPooledDataSource getDataSource() throws PropertyVetoException
// Define a variable to hold the result
ComboPooledDataSource ds = new ComboPooledDataSource();
System.out.println("URL: " + jdbcUrl);
System.out.println("Username: " + jdbcUsername);
System.out.println("Password: " + jdbcPassword);
// Set the properties for the data source
ds.setJdbcUrl(jdbcUrl);
ds.setUser(jdbcUsername);
ds.setPassword(jdbcPassword);
// Return the result
return ds;
最后但同样重要的是,属性文件:
jdbc.url=jdbc:hsqldb:hsql://localhost/test
jdbc.username=myusername
jdbc.password=mypassword
System.out.println 语句对每个阻止我的数据源设置的值都返回“null”。
谁能告诉我我做错了什么?谢谢!
【问题讨论】:
您打算向properties-config.xml
添加内容吗?如果没有,您只需将@PropertySources
添加到@Configuration
类。
顺便说一句,你有类型。应该是`@Value("$jdbc.password")`
【参考方案1】:
我终于找到了问题。实际上,有两个。首先,Bean 定义的顺序似乎很重要。一旦我将它们重新排序为更合适的顺序(即,首先创建 beanA,beanB 引用 beanA,beanC 引用 beanA 和 beanB),它似乎有所作为。
然而,主要问题是 HibernateConfiguration
类中有 PersistenceAnnotationBeanPostProcessor
的 Bean 定义。这个定义就是为什么 Environment
变量为 null 并且没有解析任何属性的原因。
感谢@Artem Bilan 的所有帮助!
【讨论】:
BeanPostProcessor
s 必须配置为 static
@Bean
并且正确,它们不应该与其他 bean 有任何依赖关系。用static
标记它们允许首先配置BPP
,然后才配置所有其他内容:其他bean 的自动装配、属性占位符等
我对此赞不绝口。这正是我的问题。是的,当使用休眠时,我也使用 PersistenceAnnotationBeanPostProcessor,但是没有其他解决方案提到这个 bean 也必须是静态的。这是有道理的,但直到现在才明显。非常感谢!
“订购”的事情让我头疼了好几个小时。真的很失望,这并不容易配置。阅读此答案后,终于可以正常工作了。【参考方案2】:
真正的问题是注解配置是在任何导入的 XML 之前加载的,您确实必须将属性占位符配置移动到 @Configuration
:
@Configuration
@PropertySource("classpath:db.properties")
public class HibernateConfiguration
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
return new PropertySourcesPlaceholderConfigurer();
请注意propertySourcesPlaceholderConfigurer
bean 的定义。没有它,您只能使用自动连接的Environment
从文件中访问您的属性。
从这里开始,属性占位符配置也可用于导入的 xml。
更多信息参见PropertySource
JavaDocs
【讨论】:
所以这是许多其他线程提供的最常见的解决方案之一,但它仍然对我不起作用。我将“@ImportResource”注释更改为“@PropertySource”并将其指向“classpath:db.properties”并添加了静态 PropertySourcesPlaceholderConfigurer 方法,但没有运气。那我读错了Spring文档吗?我以为我每行都在跟踪它?classpath:db.properties
真的是正确的路径吗?您真的使用该文件中的正确密钥吗?
是的,它是正确的路径,是的,如您所见,键是正确的 - 我已修正错字,谢谢!当我有一个纯 XML 配置时,这是提供正确工作路径的部分:<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="ignoreUnresolvablePlaceholders" value="false" /> <property name="location" value="classpath:db.properties" /> </bean>
好的。我建议你调试你的应用程序:看看Environmet
有什么;尝试使用PropertiesFactoryBean
加载您的文件。顺便说一句,你用@Bean
标记了propertySourcesPlaceholderConfigurer()
吗?
是的,我已经完全按照上面的方式标记了它。以上是关于带有注释的 Spring 4 PropertyPlaceholder的主要内容,如果未能解决你的问题,请参考以下文章
带有 spring 注释方法的 Java .parallelStream()
带有 @EnableJpa* 注释的 Spring @WebMvcTest
带有注释的 Spring + Hibernate:没有 Hibernate Session 绑定到线程
如何为带有注释的 spring 设置 context.xml?
带有 PropertyPlaceholderConfigurer bean 的 Spring @Configuration 文件不解析 @Value 注释