So the reason this doesn't work is because your BeanDefinitionParser works much earlier than placeholders will be eliminated. A simple overview, as I understand it:
- BeanDefinitionParsers parse XML in BeanDefinition objects in memory
- BeanDefinitions are then loaded into BeanFactory
- BeanFactoryPostProcessors (including property placeholder configurators) run in bean definitions
- beans are created from bean definitions
(Of course, other things happen along the way, but these are important steps here.)
So, in order to get the allowed value of the property in your Vector3D object, I think you will have to defer the arguments to the Vector3D constructor until BeanFactoryPostProcessors are started. One way that arises for me is for your BeanDefinitionParser to build a bean definition for Spring FactoryBean instead of Vector3D itself. Then the splitting of the vector value that you have on your Vector3DBeanDefinitionParser should be in the FactoryBean implementation instead.
Sorry, I'm not very familiar with Scala, so this will be in Java.
The FactoryBean class will look something like this:
import org.springframework.beans.factory.FactoryBean; public class Vector3DFactoryBean implements FactoryBean<Vector3D> { private String delimiter; private String value; private transient Vector3D instance; public String getDelimiter() { return delimiter; } public void setDelimiter(String delimiter) { this.delimiter = delimiter; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } @Override public Vector3D getObject() { if (instance == null) { String[] values = value.split(delimiter); instance = new Vector3D( Double.parseDouble(values[0]), Double.parseDouble(values[1]), Double.parseDouble(values[2]) ); } return instance; } @Override public Class<?> getObjectType() { return Vector3D.class; } @Override public boolean isSingleton() { return true; } }
Then your Vector3DBeanDefinitionParser will simply pass delimiter and value intact to the definition of the Vector3DFactoryBean bean:
class Vector3DBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { override def getBeanClass(element : Element) = classOf[Vector3DFactoryBean] override def doParse(element: Element, builder: BeanDefinitionBuilder) { val delim = element.getAttribute("delimeter") val value = element.getAttribute("value") builder.addPropertyValue("delimiter", delim) builder.addPropertyValue("value", value) } }
Then, when the placeholder properties configurator starts, it must resolve the property values ββin the Vector3DFactoryBean bean definition. When beans are finally created from bean definitions, Vector3DFactoryBean will parse the vector values ββand create a Vector3D object.