Spring XML-Based DI and Builder Pattern
This quick tutorial covers creating Spring beans for classes created with the Builder pattern using XML.
Join the DZone community and get the full member experience.
Join For FreeRecently, I faced a situation where a project was using Spring for its business layer and maintains the Spring dependencies in an XML file. They cannot upgrade this XML-based configuration to a Java-based configuration. It's an old project, it will take time, and they can't afford it.
That's fine, but the problem is that they want to add a third-party module to re-use some utilities from that library. When they try to incorporate the aforesaid module, they discovered that many classes that are exposed as services were created using the Builder pattern. So we will see how we can incorporate the Builder pattern in Spring XML-based DI.
Builder Pattern
The Builder pattern is used to create complex objects — which have some required and some optional parameters.
We create a static inner class called Builder and pass the required parameters in the constructor of that Builder. Then, set optional parameters calling the Setter method of that Builder.
Lastly, it has a build() method, which will produce the actual object.
Say we create an Employee object using the Builder pattern, where the id and the name of the employee are mandatory, but hobbies, gender, and address are optional.
package com.example.advanceSpring.entity;
public class Employee {
private Long id;
private String name;
private int gender;
private String address;
private String hobby;
private Employee() {}
public static class EmployeeBuilder{
private Long id;
private String name;
private int gender;
private String address;
private String hobby;
public EmployeeBuilder(Long id, String name) {
this.id=id;
this.name=name;
}
public void setGender(int gender) {
this.gender = gender;
}
public void setAddress(String address) {
this.address = address;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public Employee build() {
Employee emp = new Employee();
emp.id=id;
emp.name=name;
emp.gender=gender;
emp.address=address;
emp.hobby=hobby;
return emp;
}
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", gender="+( gender == 1?"Male":"Female") + ", address=" + address + ", hobby="
+ hobby + "]";
}
}
Creating the Bean
Let's say this class comes from a third party JAR and we need to create an Employee object using Spring XML-based dependency injection.
How can we do that?
Register the builder class using the context of Employee class with
$
. So the class attribute will beclass =”com.example.advanceSpring.entity.Employee$EmployeeBuilder”
. By doing this, Spring will understand that Employee builder is an inner class of Employee.Pass the required parameters using
constructor-args
.Pass the optional parameter using the
property
tag.Register the Employee bean in Spring XML. While registering, one thing you can notice is that the
Employee
object constructor is private, so the Spring bean can’t call it by reflection. So we will use the factory-bean and the factory-method attribute of Spring XML.
Thefactory-bean
attribute tells Spring to use the bean as a Factory class for creating the Object, so here, Spring treats EmployeeBuider as a Factory of Employee Object.
Thefactory-method
attribute tells Spring, upon calling the method instance of the Object, to return, so here, the build() method acts as a factory method to create the Employee Object.<beans xmlns="http://www.springframework.org/schema/beans" 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-2.5.xsd"> <bean id="helloBean" class="com.example.advanceSpring.HelloWorld"> <property name="name" value="Shamik" /> </bean> <bean id="builder" class="com.example.advanceSpring.entity.Employee$EmployeeBuilder"> <constructor-arg value="1"/> <constructor-arg value="Shamik Mitra"/> <property name="gender" value="1"/> <property name="hobby" value="Blogging"/> </bean> <bean id="employee" class="com.example.advanceSpring.entity.Employee" factory-bean="builder" factory-method="build"/> </beans>
Now we will test the settings.
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.example.advanceSpring.entity.Employee; public class SpringTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "SpringTest.xml"); Employee employee = (Employee) context.getBean("employee"); System.out.println(employee); } }
Output:
Employee [id=1, name=Shamik Mitra, gender=Male, address=null, hobby=Blogging]
Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments