Announcement Announcement Module
Collapse
No announcement yet.
Lookup Method Injection - Not creating distinct instance. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Lookup Method Injection - Not creating distinct instance.

    Hi Folks,
    I'm new to spring, and learning it from Apress Prospring3 book.
    I'm trying an example from that book on "Lookup Method Injection" which demonstrates that new instance of bean is created during each call of lookup method.
    But When I tried the example, I don't see new instance is created for each call? Could someone point me what is wrong?

    Here is the code:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
    	<bean id="helper" class="com.adi.prospring.ch4.methodInjection.MyHelper" />
    
    	<bean id="abstractJobToDo" class="com.adi.prospring.ch4.methodInjection.AbstractJobToDo">
    		<lookup-method name="getHelper" bean="helper" />
    	</bean>
    	
    	<bean id="standardJobToDo" class="com.adi.prospring.ch4.methodInjection.StandardJobToDo">
    		<property name="helper">
    			<ref local="helper" />
    		</property>
    	</bean>
    
    </beans>
    
    =================================
    package com.adi.prospring.ch4.methodInjection;
    
    public class MyHelper {
    
    	public void doSomeThing() {
    
    	}
    }
    ==================================
    package com.adi.prospring.ch4.methodInjection;
    
    public interface JobToDo {
    
    	public MyHelper getHelper();
    
    	public void doIt();
    }
    ===================================
    package com.adi.prospring.ch4.methodInjection;
    
    public abstract class AbstractJobToDo implements JobToDo {
    
    	@Override
    	public abstract MyHelper getHelper();
    
    	@Override
    	public void doIt() {
    		getHelper().doSomeThing();
    	}
    
    }
    =====================================
    package com.adi.prospring.ch4.methodInjection;
    
    public class StandardJobToDo implements JobToDo {
    
    	private MyHelper helper;
    
    	@Override
    	public MyHelper getHelper() {
    		return this.helper;
    	}
    
    	@Override
    	public void doIt() {
    		getHelper().doSomeThing();
    
    	}
    
    	public void setHelper(MyHelper helper) {
    		this.helper = helper;
    	}
    
    }
    =========================
    Main class:
    package com.adi.prospring.ch4.methodInjection;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.util.StopWatch;
    
    public class ExecuteJobs {
    
    	public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext(
    				"com/adi/prospring/ch4/methodInjection/xmlBeanFactory.xml");
    
    		JobToDo standardJobToDo = ctx.getBean("standardJobToDo", JobToDo.class);
    		JobToDo abstractJobToDo = ctx.getBean("abstractJobToDo", JobToDo.class);
    
    		displayInfo(standardJobToDo);
    		displayInfo(abstractJobToDo);
    	}
    
    	private static void displayInfo(JobToDo jobToDo) {
    		StopWatch stopwatch = new StopWatch();
    		stopwatch.start("methodInjectionDemo");
    
    		MyHelper helper1 = jobToDo.getHelper();
    		MyHelper helper2 = jobToDo.getHelper();
    
    		System.out.println(jobToDo.getClass().getName()
    				+ " : is helper1==helper2? :" + (helper1 == helper2));
    		System.out.println("helper1=" + helper1);
    		System.out.println("helper2=" + helper2);
    		for (int x = 0; x < 100000; x++) {
    			MyHelper helper = jobToDo.getHelper();
    			helper.doSomeThing();
    		}
    		jobToDo.doIt();
    		stopwatch.stop();
    		System.out.println("Time elapsed=" + stopwatch.getTotalTimeMillis()
    				+ "ms");
    
    	}
    
    }
    ==============================
    Here is code output, which shows new instance is not created for each of getHelper() on abstractJobToDo instance.
    Code:
    com.adi.prospring.ch4.methodInjection.StandardJobToDo : is helper1==helper2? :true
    helper1=com.adi.prospring.ch4.methodInjection.MyHelper@558352d8
    helper2=com.adi.prospring.ch4.methodInjection.MyHelper@558352d8
    Time elapsed=5ms
    com.adi.prospring.ch4.methodInjection.AbstractJobToDo$$EnhancerByCGLIB$$7f0cfb5f : is helper1==helper2? :true
    helper1=com.adi.prospring.ch4.methodInjection.MyHelper@558352d8
    helper2=com.adi.prospring.ch4.methodInjection.MyHelper@558352d8
    Time elapsed=149ms

  • #2
    What scope is assigned to the helper bean? Shouldn't it be prototype?

    <bean id="helper" class="com.adi.prospring.ch4.methodInjection.MyHel per" scope="?"/>

    Just a thought...

    Jeff
    Last edited by visualjeff; Jul 24th, 2012, 03:06 PM.

    Comment


    • #3
      As Jeff pointed out, Spring beans are singletons by default, so what is displayed is normal behaviour. If you want a different instance every time you call getBean(), you need to specify prototype scope.

      However, in your case, that evidently wouldn't change much: this is because MyHelper is a field of the StandardJobToDo class, and you only getBean() for that class once. Thus, even with prototype scope on MyHelper, you would get the same instance of MyHelper which is the one saved inside the only StandardJobToDo instance which is instantiated.
      Your code shows poor understanding of dependency injection, scopes, and the mechanics of the Spring framework; I suggest a more torough study of the theory before going 'hands-on'.

      Comment


      • #4
        However, in your case, that evidently wouldn't change much: this is because MyHelper is a field of the StandardJobToDo class, and you only getBean() for that class once. Thus, even with prototype scope on MyHelper, you would get the same instance of MyHelper which is the one saved inside the only StandardJobToDo instance which is instantiated.
        That's true but the original post did *not* expect to see different instance in the StandardJobToDo case. Instead the original post expected the abstractJobToDo case to show different instances, which is correct. Here it is:

        Here is code output, which shows new instance is not created for each of getHelper() on abstractJobToDo instance.
        So with changing the scope of the 'helper' bean to 'prototype' in original posted code, you should see the different instances being returned in the abstractJobToDo case. That is Spring's Method Lookup Injection in action. Helpful this clarifies up some misunderstanding.
        Last edited by tannoy; Jul 31st, 2012, 02:44 PM.

        Comment

        Working...
        X