Spring static factory method Example

0

Consider the use case where one of your constructor argument expects a library object and the only way you can instantiate the library class is using its static factory method, then you need to find a way to create the library bean in the XML context and make the constructor argument refer to the bean.

Spring Container creates the bean by calling either its constructor, using reflection, or using the static factory method if the factory class and factory method are specified in the XML.
The object type returned from the invocation of the static factory method may be the same class or another class entirely.

Note that the object type returned from the invocation of the static factory method may be the same class or another class entirely. In this article, I will show you the first case where class Name creates its own instance calling Name.getInstance(string).

How to instantiate a bean in spring using static factory method?

Let’s see an example. In the below XML, we create an instance of java.text.NumberFormat. The way you create an instance in java is:

java.text.NumberFormat.getInstance(new Locale("de"))

The same can be achieved in XML by specifying the factory class in class attribute and the factory method getInstance in factory-method attribute. Since Locale conversion is handled by spring automatically so we just need to pass the language string to it. See Spring Default PropertyEditor for more details.

<bean id="germanNumberFormat" class="java.text.NumberFormat"
		factory-method="getInstance">
    <constructor-arg value="de" />
</bean>

Let’s see one more example and then we will create our own factory class and method.
Below, we are getting a Double value, spring will invoke Double.valueOf(20d).

<bean id="doubleValue" class="java.lang.Double" factory-method="valueOf">
    <constructor-arg value="20d" type="double" />
</bean>

Creating Bean by Invoking a Static Factory Method

Let’s first define the factory class.

Name:

package com.javarticles.spring;

public class Name {
    private String value;
    private Name(String value) {
        this.value = value;
    }
    public static Name getInstance(String value) {
        return new Name(value);
    }
    public String getValue() {
        return value;
    }    
    public String toString() {
        return "Name Bean: " + value;
    }
}

Just to spice it up, we will define another class AbstractNameFactory. It has an abstract method createName to create instances of Name.
We define the abstract method in the spring XML.

AbstractNameFactory:

package com.javarticles.spring;

public abstract class AbstractNameFactory {
    public abstract Name createName();
}

Let’s configure the static factory class in spring context XML.

applicationContext.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"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<bean id="germanNumberFormat" class="java.text.NumberFormat"
		factory-method="getInstance">
		<constructor-arg value="de" />
	</bean>
	<bean id="doubleValue" class="java.lang.Double" factory-method="valueOf">
		<constructor-arg value="20d" type="double" />
	</bean>

	<bean id="nameFactory"
		class="com.javarticles.spring.AbstractNameFactory">
		<lookup-method name="createName" bean="name" />
	</bean>

	<bean id="name" class="com.javarticles.spring.Name"
		factory-method="getInstance" scope="prototype">
		<constructor-arg index="0" value="Joe">
		</constructor-arg>
	</bean>
</beans>

Let’s analyse how we have defined the beans.
Bean definition for name relies on static factory method call to create instance of Name. The class is specified in the attribute class. The getInstance method is specified in factory-method attribute.

We can also refer the static factory bean in the lookup-method in case you want it to be called when the abstract method is called. In bean definition for nameFactory, we make the abstract method createName refer to the static factory bean to return the Name instance. See lookup-method example for more details.

SpringStaticFactoryInstanceExample:

package com.javarticles.spring;

import java.io.IOException;
import java.text.NumberFormat;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStaticFactoryInstanceExample {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        try {
            final NumberFormat germanNumberFormat = (NumberFormat) context.getBean("germanNumberFormat");
            System.out.println("NumberFormat: " + germanNumberFormat);
            
            Double doubleValue = (Double) context.getBean("doubleValue");
            System.out.println("Double Value: " + doubleValue);
            
            AbstractNameFactory nameFactory = (AbstractNameFactory) context
                    .getBean("nameFactory");
            System.out.println(nameFactory.createName());
        } finally {
            context.close();
        }
    }
}

Output:

NumberFormat: [email protected]
Double Value: 20.0
Name Bean: Joe

Download the source code

This was an example about spring static factory method.

You can download the source code here: springStaticFactoryInstanceExample.zip
Share.

Comments are closed.