Results 1 to 5 of 5

Thread: 'Weak' Dependencies

  1. #1
    Join Date
    Aug 2007
    Posts
    3

    Default '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:

    Code:
    <bean id="listener" scope="singleton"/>
    <bean id="teller" lazy-init="false" scope="singleton">
        <property name="listener" value="listener" />
    </bean>
    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?

    Thanks

    _jpg_

  2. #2
    Join Date
    Mar 2007
    Posts
    515

    Default

    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. #3

    Default

    I think you may be looking for something like this:

    Code:
    	<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>
    	<bean id="observer2" class="sandbox.ObservantBean">
    		<property name="listener" ref="listener"/>
    	</bean>
    	<bean id="observer3" class="sandbox.ObservantBean">
    		<property name="listener" ref="listener"/>
    	</bean>
    Where teller has a factory method to generate listeners bound to it:

    Code:
    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();
    
    		listener.setMyNum(listeners.size());
    		this.listeners.add(listener);
    		
    		System.out.println("Number of Listeners: " + listeners.size());
    		
    		return listener;
    	}
    }
    Then invoking the following

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

    Code:
    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. #4
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    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.
    http://www.springframework.org/docs/...itializingbean
    http://www.springframework.org/docs/...-extension-bpp
    Last edited by karldmoore; Aug 19th, 2007 at 03:21 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  5. #5
    Join Date
    Aug 2007
    Posts
    3

    Default

    Andrei,

    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.

    jstehler,

    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?

    _jpg_

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •