References between Spring beans when using a NameSpaceHandler
- by teabot
I'm trying to use a Spring context namespace to build some existing configuration objects in an application. I have defined a context and pretty much have if working satisfactorily - however, I'd like one bean defined by my namespace to implicitly reference another:
Consider the class named 'Node':
public Class Node {
private String aField;
private Node nextNode;
public Node(String aField, Node nextNode) {
...
}
Now in my Spring context I have something like so:
<myns:container>
<myns:node aField="nodeOne"/>
<myns:node aField="nodeTwo"/>
</myns:container>
Now I'd like nodeOne.getNode() == nodeTwo to be true. So that nodeOne.getNode() and nodeTwo refer to the same bean instance. These are pretty much the relevant parts I have in my AbstractBeanDefinitionParser:
public AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
...
BeanDefinitionBuilder containerFactory = BeanDefinitionBuilder.rootBeanDefinition(ContainerFactoryBean.class);
List<BeanDefinition> containerNodes = Lists.newArrayList();
String previousNodeBeanName;
// iterate backwards over the 'node' elements
for (int i = nodeElements.size() - 1; i >= 0; --i) {
BeanDefinitionBuilder node = BeanDefinitionBuilder.rootBeanDefinition(Node.class);
node.setScope(BeanDefinition.SCOPE_SINGLETON);
String nodeField = nodeElements.getAttribute("aField");
node.addConstructorArgValue(nodeField);
if (previousNodeBeanName != null) {
node.addConstructorArgValue(new RuntimeBeanReference(previousNodeBeanName));
} else {
node.addConstructorArgValue(null);
}
BeanDefinition nodeDefinition = node.getBeanDefinition();
previousNodeBeanName = "inner-node-" + nodeField;
parserContext.getRegistry().registerBeanDefinition(previousNodeBeanName, nodeDefinition);
containerNodes.add(node);
}
containerFactory.addPropertyValue("nodes", containerNodes);
}
When the application context is created my Node instances are created and recognized as singletons. Furthermore, the nextNode property is populated with a Node instance with the previous nodes configuration - however, it isn't the same instance.
If I output a log message in Node's constructor I see two instances created for each node bean definition.
I can think of a few workarounds myself but I'm keen to use the existing model. So can anyone tell me how I can pass these runtime bean references so that I get the correct singleton behaviour for my Node instances?