Spring 4带有注释的PropertyPlaceholder

时间:2014-03-30 15:14:29

标签: java spring spring-mvc annotations properties-file

好的,我知道这个问题已被多次询问过了,我已经尝试了他们建议的答案中的每一个解决方案,但还没有找到一个有效的解决方案,所以我希望有人在这里可以指出我正确的方向。

我正在尝试将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>

这是我的网络应用初始化程序类(反正片段):

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语句全部返回&#34; null&#34;对于阻止我的数据源进行设置的每个值。

有人可以告诉我我做错了什么吗?谢谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

终于发现了这个问题。实际上,有两个。首先,Bean定义的顺序似乎很重要。一旦我将它们重新排序为更合适的顺序(即beanA首先创建,beanB引用beanA,beanC引用beanA和beanB),它似乎有所不同。

然而,主要问题是PersistenceAnnotationBeanPostProcessor类中有HibernateConfiguration的Bean定义。这个定义是Environment变量为空且没有解析属性的原因。

感谢@Artem Bilan的所有帮助!