使用PropertySourcesPlaceholderConfigurer在多个上下文中的Spring属性

时间:2014-11-16 07:40:59

标签: spring spring-mvc properties

好的,我一直在争取这么长时间,是时候寻求帮助了。救命?! 我无法使用PropertySourcesPlaceholderConfigurer使我的属性在我的某个上下文中工作。

我有2个背景: rootContext:

AnnotationConfigWebApplicationContext rootContext = createContext(InfrastructureContextConfiguration.class);

和dispatcherContext:

AnnotationConfigWebApplicationContext dispatcherContext = createContext(WebMvcContextConfiguration.class);

这些加载如下:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
   registerListener(servletContext);
   registerDispatcherServlet(servletContext);
}

private void registerDispatcherServlet(ServletContext servletContext) {
   AnnotationConfigWebApplicationContext dispatcherContext = createContext(WebMvcContextConfiguration.class, WebFlowContextConfiguration.class);
   ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(dispatcherContext));
   dispatcher.setLoadOnStartup(1);
   dispatcher.addMapping("/");
}

private void registerListener(ServletContext servletContext) {
  AnnotationConfigWebApplicationContext rootContext = createContext(InfrastructureContextConfiguration.class );
  servletContext.addListener(new ContextLoaderListener(rootContext));
  servletContext.addListener(new RequestContextListener());
}

我创建PropertySourcesPlaceholderConfigurer并在dispatcherContext WebMvcContextConfiguration中设置@PropertySource:

@Configuration
@EnableWebMvc
@PropertySource("classpath:my.properties")
@ComponentScan(basePackages = { "com.me.my.web" })
public class WebMvcContextConfiguration extends WebMvcConfigurerAdapter {
@Bean
  public static PropertySourcesPlaceholderConfigurer  propertySourcesPlaceholderConfigurer() {
      return new PropertySourcesPlaceholderConfigurer();
   }
}

因此可以使用:

访问此dispatcherContext中的属性
@Value( "${recaptcha.private.key}" )
private String recaptchaPrivateKey;   

问题是我无法从rootContext访问这些属性。我试过了@value注释。我试图在InfrastructureContextConfiguration类中创建第二个PropertySourcesPlaceHolderConfigurer,唉!

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:my.properties")
@ComponentScan(basePackages = { "com.me.my.service", "com.me.my.repository",
  "com.me.my.domain.support" })
public class InfrastructureContextConfiguration {

//load properties from my.properties file 
@Value( "${mysql.db.driver.class}" )  //this is always null!   
private String mysqlDriverClass ;
...
}

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
   return new PropertySourcesPlaceholderConfigurer();
}  

@Bean
public DataSource dataSource() {
   BasicDataSource dataSource = new BasicDataSource();
   dataSource.setDriverClassName(mysqlDriverClass);
   ...
  }
 ...
}

更新:我已将PropertySourcesPlaceHolderConfigurer和@PropertySource(" classpath:my.properties")添加到我的InfrastructureContextConfiguration。我改变了上面的这个类来反映我的变化。使用调试器逐步执行InfrastructureContextConfiguration我最初看到任何注入的属性为null但最终它们具有值。例如,在Datasource dataSource()方法中," mysqlDriverClass"为null因此失败但稍后在此类中使用具有良好/非空值的其他注入属性构造其他bean。我可以在什么时候安全地尝试访问这些属性值?

回答我的更新我发现了我的问题。我在@Value注入属性之前声明@Autowired DataSource成员变量,因此在注入属性被解析之前,类正在初始化dataSource。

1 个答案:

答案 0 :(得分:1)

正如@Patouche所提到的,在根应用程序上下文中定义的bean可以在所有Web应用程序上下文中访问,但它没有相反的工作方式。

每个DispatcherServlet都有一个关联的web applicationContext,它继承自根Web应用程序上下文。如果您需要在根Web应用程序上下文中使用值或bean,那么您必须在那里定义它。

有关详细信息,请参阅此讨论。它还有一个指向相关Spring文档的链接。 Spring root WebApplicationContext for Servlet