Training Institute in Electronic City Bangalore

Training Institute in Electronic City Bangalore
Training Institute in Electronic City Bangalore

Spring singleton beans with prototype-bean dependencies

For most application scenarios, the majority of the beans in the container will be singletons.
When a singleton bean needs to collaborate with another singleton bean, or a non-singleton bean needs to collaborate with another non-singleton bean, the typical and common approach of handling this dependency by defining one bean to be a property of the other is quite adequate.
There is a problem when the bean lifecycles are different. Consider a singleton bean A which needs to use a non-singleton (prototype) bean B, perhaps on each method invocation on A.
The container will only create the singleton bean A once, and thus only get the opportunity to set the properties once.
There is no opportunity for the container to provide bean A with a new instance of bean B every time one is needed.
There are two solutions to this issue:
1.    Implementing BeanFactoryAware/ApplicationContextAware by bean A;
2.    Using Lookup method injection.
Here is some code examples:
Bean A 

 public class A { 
   private String text; 
   private B b; 

   public void setB(B b) { 
     this.b = b; 
   } 

   public B getB() { 
     return b; 
   } 
 
   public String getText() { 
     return text; 
   } 

   public void setText(String text) { 
     this.text = text; 
   } 
 } 


Bean B 

 public class B { 
   private String text;   

   public String getText() { 
     return text; 
   } 

   public void setText(String text) { 
     this.text = text; 
   } 
 } 


spring-config.xml 

 <?xml version="1.0" encoding="UTF-8"?> 
 <beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans  
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
       http://www.springframework.org/schema/context  
       http://www.springframework.org/schema/context/spring-context-3.2.xsd"> 
   <bean id="a" class="ua.cn.dmitrykrivenko.spring.example.A" scope="singleton" >   
     <property name="text" value="text A"/>   
     <property name="b"> 
       <ref bean="b"/> 
     </property>    
   </bean> 
   <bean id="b" class="ua.cn.dmitrykrivenko.spring.example.B" scope="prototype"> 
     <property name="text" value="text B"/>  
   </bean>  
 </beans> 

And let's create some test class:
 

 public class Test { 
   public static void main(String[] args) { 
     ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml"); 

     A a = ctx.getBean("a", A.class); 

     System.out.println("a before: " + a.getText()); 
     System.out.println("b before: " + a.getB().getText()); 

     a.setText("text A1"); 
     a.getB().setText("text B1"); 

     a = ctx.getBean("a", A.class); 

     System.out.println("a after: " + a.getText()); 
     System.out.println("b after: " + a.getB().getText()); 
   } 
 } 

The output will be looks like this: 

 a before: text A 
 b before: text B 
 a after: text A1 
 b after: text B1 

As you see inside singleton bean A another bean B("prototype") is used as singleton too. 

1.  Implementing BeanFactoryAware/ApplicationContextAware by bean A

Change bean A 

 public class A implements ApplicationContextAware
   private String text;   
   private ApplicationContext applicationContext;
   
   public B getB() { 
     return applicationContext.getBean("b", B.class); 
   }  
   public String getText() { 
     return text; 
   } 
   public void setText(String text) { 
     this.text = text; 
   } 
   public void setApplicationContext(ApplicationContext ac) throws BeansException { 
     this.applicationContext = ac; 
   } 
 } 


and spring-config.xml 

   <bean id="a" class="ua.cn.dmitrykrivenko.spring.example.A" scope="singleton" >   
     <property name="text" value="text A"/>   
   </bean> 
   <bean id="b" class="ua.cn.dmitrykrivenko.spring.example.B" scope="prototype"> 
     <property name="text" value="text B"/>  
   </bean>  


And run test class again. You'll see: 
 a before: text A 
 b before: text B 
 a after: text A1 
 b after: text B 


But this example is generally not a desirable solution since the business code is then aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, allows this use case to be handled in a clean fashion. 

2. Lookup method injection

Lookup method injection refers to the ability of the container to override methods on container managed beans, to return the result of looking up another named bean in the container. The Spring Framework implements this method injection by dynamically generating a subclass overriding the method, using bytecode generation via the CGLIB library.

Change bean A like this
 public abstract class A{ 
   private String text;

   public abstract B getB(); 

   public String getText() { 
     return text; 
   } 
   public void setText(String text) { 
     this.text = text; 
   } 
 } 


or like this

 public class A{ 
   private String text;

   public B getB(){
     return null;
   }
   public String getText() { 
     return text; 
   } 
   public void setText(String text) { 
     this.text = text; 
   } 
 } 


and spring-config.xml 

   <bean id="a" class="ua.cn.dmitrykrivenko.spring.example.A" scope="singleton" >   
     <property name="text" value="text A"/>  
      <lookup-method name="getB" bean="b"/>     
   </bean> 
   <bean id="b" class="ua.cn.dmitrykrivenko.spring.example.B" scope="prototype"> 
     <property name="text" value="text B"/>  
   </bean>  

After running  test class again you'll see:

 a before: text A 
 b before: text B 
 a after: text A1 
 b after: text B 

That means we get new instance of B every time ("prototype" scope).
If the method is abstract, the dynamically-generated subclass will implement the method. Otherwise, the dynamically-generated subclass will override the concrete method defined in the original class.




[Spring Interview Questions]

We recommend you take Big Data Hadoop class room training at eMexo Technologies in electronic city, Bangalore to learn more about Big Data Hadoop.

0 Comments:

© Blogger Templates | Webtalks