Spring 3.1 PropertySourcesPlaceholderConfigurer an

2019-02-06 16:41发布

问题:

Looking at the new spring property support in 3.1 ( http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/ ), it looks like this should be possible:

<context:property-placeholder location="/WEB-INF/application-customer-dev.properties,classpath:application-customer.properties" ignore-resource-not-found="true"/>

<import resource="classpath*:com/x/core/security/security-${login.security}.xml"/>

where login.security is in application-customer-dev.properties as:

login.security=dev

(and security-dev.xml does exist in the appropriate place). I am missing something though, as login.security is not able to be resolved. I would expect this behavior in versions of spring prior to 3.1, but it looks like this should be valid with 3.1 (which we are using)?

回答1:

Footnote [2] of your link:

[2]: Because processing of <import/> elements necessarily occurs before BeanFactoryPostProcessors are invoked, meaning that even PropertyPlaceholderConfigurer could not help here. Because the Environment and its set of PropertySources are configured before container refresh, placeholders in elements can be resolved against the Environment without any lifecycle issues.

UPDATE:

According to the javadoc for PropertySourcesPlaceholderConfigurer, PropertySourcesPlaceholderConfigurer is a BeanFactoryPostProcessor, so what the footnote really says is that the import is resolved before the PropertySourcesPlaceholderConfigurer is installed, so it will not work either (in fact, at the time the <import/> is resolved, the configurer might not even exist yet!) Yes, when it is installed it will look at the Environment, but you cannot use it to resolve inside an <import/>, because at that time no postprocessors are operative. And that includes PropertySourcesPlaceholderConfigurer.

Basically Spring XML context setup goes more or less like this:

  1. Context is created.
  2. Environment is set.
  3. XML is read (all XML, resolving imports if necessary). Bean definitions are created.
  4. BeanFactoryPostProcessors are installed and invoked, processing bean definitions.
  5. BeanPostProcessors are installed.
  6. Beans are instantiated according to the bean definitions. BeanPostProcessors are applied.

This is a similar problem as that which causes that you cannot use the order property of many postprocessors to apply a BeanPostProccesor before a BeanFactoryPostProcessor (to do something like make a PropertyPlaceholderConfigurer resolve placeholders from a @PersistenceContext): the behaviour is hardcoded in the Spring application context, so you have to work around it by specializing some Spring classes.



回答2:

I think you are mis-reading the blog a little @Kurt - It should be resolved IF the property source containing the property is present before the bean definitions are starting to be created.

So the way to get your import to resolve will these two ways: 1. set an environment variable with this parameter (-Dlogin.security=dev) which will be registered as a property source by default
2. to register a file as a property source programatically, mentioned in the blog article by writing a custom ApplicationContextInitializer to register your property source - you should be able to use a ResourcePropertySource to register your file based property source



回答3:

It should be much easier to what you need now by @Inject Environment and using profiles. You shouldn't need to replace part of a file name.