Announcement Announcement Module
No announcement yet.
'Weak' Dependencies Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • 'Weak' Dependencies

    I currently have a observer type pattern which I need to represent in my spring XML configuration. Originally I did this like this:

    <bean id="listener" scope="singleton"/>
    <bean id="teller" lazy-init="false" scope="singleton">
        <property name="listener" value="listener" />
    This meant that whenever I retrieved a (well, the) listener, there was already a teller attached to it (and already telling it things).

    The problem is now that I want lots of tellers/listeners, so they cannot be singletons any more. I really need a configuration which says on the 'listener' bean that it has a 'weak' dependency on the 'teller' bean - i.e. instantiate it afterwards with the original 'listener' bean as the dependency.

    Of course I could code the 'listener' to automatically lookup a 'teller' and attach itself to it, but of course I'd rather inject this.

    Is this possible? Am I going about this the wrong way?



  • #2
    Couldn't you just simply make both beans as 'prototype' and when retrieving a 'listener' you'll have a new Listener attached to a new Teller ?


    • #3
      I think you may be looking for something like this:

      	<bean id="teller" class="sandbox.Teller"/>
      	<bean id="listener" scope="prototype"
      		factory-bean="teller" factory-method="addListener" />	
      	<bean id="observer1" class="sandbox.ObservantBean">
      		<property name="listener" ref="listener"/>
      	<bean id="observer2" class="sandbox.ObservantBean">
      		<property name="listener" ref="listener"/>
      	<bean id="observer3" class="sandbox.ObservantBean">
      		<property name="listener" ref="listener"/>
      Where teller has a factory method to generate listeners bound to it:

      public class Teller {
      	private List listeners = new ArrayList();
      	public void tellAll(String s){
      		for( int i = 0; i < listeners.size(); i++ )
      			((Listener) listeners.get(i)).tellMe(s);
      	public synchronized Listener addListener(){
      		Listener listener = new Listener();
      		System.out.println("Number of Listeners: " + listeners.size());
      		return listener;
      Then invoking the following

      Teller teller = (Teller) ctx.getBean("teller");
      teller.tellAll("Hello, World");
      results in

      Number of Listeners: 1
      Number of Listeners: 2
      Number of Listeners: 3
      Listener 0: Hello, World
      Listener 1: Hello, World
      Listener 2: Hello, World


      • #4
        You can inject the listener into all your beans and then call the addListener method with an initialization callback method. A BeanPostProcessor however might be a cleaner solution.
        Last edited by karldmoore; Aug 19th, 2007, 03:21 AM.


        • #5

          I can't simply mark both as prototype because the listener has no direct dependency on the teller, so the teller will not be created.


          I don't want to do this because (a) I have an arbitrary number of teller/listeners so can't put them in my xml file like this and (b) I don't want to hardcode the addListener method to create a specific implementation on a Listener.


          Instead what I have decided to do is to create a DependentBeanFactoryFactory (or similar) which will provide beans which are actually dependencies of other beans. This means that it will create a 'teller' bean, then return it's 'listener', meaning that both will be scoped as prototypes and both will be created by a creation request for either. Does this sound like a reasonable solution? Are there any better ones?