In Spring can you alter property placeholder values using a BeanDefinitionDecorator?
I have a BeanDefinitionDecorator that makes modifications to properties that a user would set on a bean. It works fine; except if the bean is using placeholders. I am trying to find a strategy to modify those values while still have access to the original value at runtime. An example of what this would look like in XML:
<bean id="bean">
<property name="jdbcUrl" value="${jdbc.url}" />
<d:spyDecorator />
</bean>
I know that user would be writing the jdbcUrl property as "jdbc:myDatabase". What I want to do is change their property to "jdbc:spy:myDatabase". This is easy if they are just using string literals for the property value,开发者_如何学Python but if they are using property placeholders I am not sure how to change the value -- because I need the original value in order to supply the new value. They key is to keep the property rewriting transparent to the user.
Are there any possible solutions for this?
I think your namespace handler can register a BeanFactoryPostProcessor
(implementing Orderer
with order = Integer.MAX_VALUE
to be the last post processor applied). Then your BeanDefinitionDecorator
will register the beans being decorated for processing with that post processor (implement it in the post processor somehow), and post processor will apply the actual property modification to that beans.
You can use PropertyPlaceholderConfigurer
to substitute property values for placeholders in bean properties, aliases, and other places. Note that the replacements happen AFTER the bean definitions have been loaded, so this mechanism does not apply to <import>
elements
For example:
...
<bean id="ppc"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:build.properties</value>
<value>classpath:default-emmet-substitution.properties</value>
<value>classpath:default-danno-substitution.properties</value>
<value>classpath:default-dannotate-substitution.properties</value>
<value>classpath:substitution.properties</value>
</list>
</property>
</bean>
...
For more information refer to this section of the Spring Framework docs.
EDIT - I guess from your comment you are already familiar with how placeholder replacement works, and are using PropertyPlaceholderConfigurer
to do the replacements. So now you need to choose between these strategies, or some combination:
Do the placeholder replacements yourself in your custom
BeanDefinitionDecorator
. That would work, though you'd be duplicating a lot of code.Have the custom
BeanDefinitionDecorator
modify the placeholder names to different ones that will pull in different values; e.g."${jdbc.url}"
becomes"${spy.jdbc.url}"
.Extend the
PropertyPlaceholderConfigurer
class to modify the substituted property values; i.e. overrideconvertProperty
orconvertProperties
. That has the potential problem that all placeholders will get the modified values ... not just the ones in beans that you have decorated.Create a new
PropertyResourceConfigurer
class to substitute different property values depending on the context. Essentially, theprocessProperties
needs to work like the method does in aPropertyPlaceholderConfigurer
, but do something different if it sees bean properties or whatever that tell it to do the "spy" substitution.
A combination of 2) and 3) looks the most promising.
精彩评论