Sunday, April 27, 2014

Creating Spring beans using Factory method

We all know we never need to create bean dependencies in Spring with new operator like below

e.g   Employee employee=new Employee();


Usually we use constructor or setter methods to inject dependencies.But there are other ways we can create objects in Spring.In some classes its possible that there wont be any public constructor available(E.g.: Creating java singletons objects).In these cases we don't have any option other than using the factory patterns to create objects in Spring.

Please note if you are testing the beans with private constructor in a normal java program using main program, it wont be a problem.Spring is able to create beans with private constructors using reflection.But if there is a SecurityManager in place and it wont let create beans with private constructors.

1)Static factory method:Let's say we have a static factory which is responsible for creating Singleton object(Java base Singleton object).We can use Spring bean factory-method attribute in our Spring bean definition file to wire the object.
2)Instance factory method: These objects are created using the bean instance.

Let us see creating bean instance using Static factory method and Instance factory method in action.

Lets say i have Account interface with few methods and SavingsAccount and CurrentAccount implement this interface

Account.java


 public interface Account{  
 void deposit();  
 void withdraw();  
 }  

SavingsAccount.java


public class SavingsAccount{  
 public void deposit(){  
 System.out.println("Inside Deposit method");  
 }  
 public void withdraw(){  
 System.out.println("Inside Withdraw method");  
 }  
 }   

CurrentAccount.java


public class CurrentAccount{  
 public void deposit(){  
 System.out.println("Inside Deposit method");  
 }  
 public void withdraw(){  
 System.out.println("Inside Withdraw method");  
 }  
 }   


Now we need a factory to create SavingsAccount and CurrentAccount instances.

public class AccountService{  
      private static AccountService service = new AccountService();  
      //Static factory method  
      public static AccountService createService(){  
           return service;  
      }  
      //Instance factory methods  
      public Account createSavingsAccountInstance(){  
           return new SavingsAccount();  
      }  
      public Account createCurrentAccountInstance(){  
           return new CurrentAccount();  
      }  
 }  


Now lets see how to configure bean definition file to call these factory methods.

These below two are important attributes in our spring context file to call the factory instance method and factory bean methods

1) factory-method
2)factory-bean

application-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"  
      xmlns:context="http://www.springframework.org/schema/context"  
      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.2.xsd  
 http://www.springframework.org/schema/context  
 http://www.springframework.org/schema/context/spring-context-3.2.xsd">  
      <bean id="accountService" class="com.ramesh.AccountService" factory-method="createService"/>  
      <bean id="createSavingsAccountInstance" factory-bean="accountService" factory-method="createSavingsAccountInstance"/>  
      <bean id="createCurrentAccountInstance" factory-bean="accountService" factory-method="createCurrentAccountInstance"/>  
 </beans>  



Lets test this code

com.ramesh;  
 import org.springframework.context.support.ClassPathXmlApplicationContext;  
 public class SpringApplicationContextLoader{  
      public static void main (String args[]){  
           ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");  
           Account savings = (SavingsAccount)applicationContext.getBean("createSavingsAccountInstance");  
           savings.withdraw();  
           Account current = (CurrentAccount)applicationContext.getBean("createCurrentAccountInstance");  
           current.deposit();  
      }  
 }  



I hope you get the concept :-)

Thanks for reading!!!!!