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.