References between Spring beans when using a NameSpaceHandler

Posted by teabot on Stack Overflow See other posts from Stack Overflow or by teabot
Published on 2010-06-03T16:59:36Z Indexed on 2010/06/03 18:04 UTC
Read the original article Hit count: 293

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?

© Stack Overflow or respective owner

Related posts about java

Related posts about spring