Search This Blog

Sunday 29 April 2012

Bean Creation via Factory Method

The Spring Container does not have to instantiate beans via using the new keyword. Some times objects are created from factories. There are two ways to achieve the same - via a static factory method or via an instance factory method.
Static factory method:
Consider the static method in the SingerFactory class
public class SingerFactory {
    public static synchronized Singer createSinger(final String song) {
        Singer singer = new Singer();
        singer.setSong(song);
        return singer;
    }
}
As can be seen the Factory class is now responsible for creation of all Singers. So we now need Beans that are not created by the Spring Container, but only manged by the container. The XML configuration for the same would be:
<bean id="factoryMadeSingerBean" class="com.performer.SingerFactory"
    factory-method="createSinger" >
    <constructor-arg  value="Wake Me Up When September Ends" />
</bean>
The class attribute here refers to the factory class. The factory-method attribute specifies the method to be executed to return the bean. Spring expects to call the method and get an object which it treats as a bean. The constructor arguments specified in the bean definition are the method parameters. In this case it will be used to pass in as arguments to the constructor of the Singer class
If were to test the code
public static void main(String[] args) {
    XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
    IPerformer factoryMadeSingerBean = (IPerformer) beanFactory.getBean("factoryMadeSingerBean");
    factoryMadeSingerBean.perform();
}
The output indicates that Spring container used the factory method to create the bean.
Creating a singer instance com.performer.Singer@14c1103
singing Wake Me Up When September Ends....
The other technique is to use an instance factory method.
In this technique, an instance method of a pre-existing bean is used to create another bean.
<bean id="musician" class="com.performer.Musician">
</bean>
<bean id="duplicateBean" factory-bean="musician" factory-method="createDuplicate" >
    <constructor-arg ref = "musician3"/>
</bean>
The factory-bean attribute refers to the bean instance and the factory method refers to the instance factory method. The class attribute must be left empty here. The createDuplicate() method is as below:
public Musician createDuplicate(final Musician musician) {
    final Musician newMusician = new Musician();
    newMusician.setInstrument(musician.getInstrument());
    return newMusician;
}
I executed the bean creation code and saw the output
public static void main(String[] args) {
    XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
    IPerformer duplicateBean = (IPerformer) beanFactory.getBean("duplicateBean");
    duplicateBean.perform();
}
Output:
Creating new Musiscian Object com.performer.Musician@1592174
Playing instrument Violin...

7 comments:

  1. very nice way to explain about spring factory-bean factory-method.

    ReplyDelete
  2. Nice..and good example..

    ReplyDelete
  3. If it is possible to use,how to use a non-static method to initialize a particular property of bean?

    I have bean named "contextstartedhandler" which has a getmessage method which is'nt static(i dont want it to be static as it uses non-static variables of its class) and inside it i'll intialze a "message".How can i specify to intialize this property called message of that bean in the config.xml file in definition

    1)

    2)


    above codes are throwing exception

    ReplyDelete
  4. Sorry, parts of your question are missing. From what I understood, you have a bean 'contextstartedhandler' and want to use its instance method to initialize another bean named 'message'.
    If my understanding is right than this is a case of instance factory method.

    ReplyDelete
  5. Very helpful, got me around a problem I was having with instantiating an EasyMock mock with IMocksControl through Spring. Thanks!

    ReplyDelete