Categories
Spring Spring Core

Instance Factory Method in Spring

The IoC container will invoke a non-static method of an Existing Bean to Instantiate an Object. 

In our previous example we saw how Instantiation of Bean using Constructor args and Static-Factory Method with an Example. Now we will look at how Instantiation of Instance Factory Method works in Spring with an Example.

Example of Instance Factory Method in Spring

Please look at the below flow diagram that will help you understand what is happening in the Instance Factory Method initialization in Spring IoC Container.

The above diagram shows the Flow of the Example Program given in this article.

  1. Ioc Container will read the Bean Definition from ApplicationContext.xml file and then instantiate the EmployeeController Bean. 
  2. Then the Container will invoke either createPermanentEmployeeInstance method or createContractEmployeeInstance method in EmployeeServiceLocator based on the Bean Definition we gave. 
  3. Those methods from ServiceLocator class are responsible to create an Instance and return to the IoC Container. 
  4. Finally IoC Container will inject the dependency to the EmployeeController Bean.

Let us see step by step procedure to create a running example on Instance Factory instantiation using Spring Framework.

In this example i’m using JDK 8 and Spring Framework 5.

Step 1 : Create a Java Project in Eclipse

Name it EmployeeController and Click on Finish.

Your folder structure will be like the below screenshot.

Step 2 : Convert to Maven Project

Right click on your project name → Select Configure option → Click on Convert to Maven Project and click on Finish. 

If you follow the above steps you can see your normal Java Project will be converted to Maven Project and the Pom file will get generated.

Step 3 : Add dependencies into the Pom.xml file.

We have to add Spring Framework dependencies in the Pom.xml file to make our example code working. 

We want spring-context and spring-beans jar files for this example project, to add these 

  • Goto https://mvnrepository.com/  
  • Search “Spring-beans” in the search bar. 
  • Click on Spring Beans from search results.
  • Click on 5.2.5 Release version from a table
  • Finally click on the Maven dependencies as shown below to copy
  • Goto pom.xml file from your project 
  • Create <dependencies></dependencies> tag just above the </project> tag 
  • Paste the copied maven dependency in between <dependencies> tag.
  • Follow the same approach to copy the spring-context dependency from maven repository and paste after the spring-beans dependency and save the pom.xml.

Step 4 : ServiceLocator class

Create ServiceLocator class under net.geekcoders.service package and name it as EmployeeServiceLocator and add below code in it.

package net.geekcoders.service;

public class EmployeeServiceLocator {
	private PermanentEmployeeServiceImpl permanentEmployeeServiceImpl = new PermanentEmployeeServiceImpl();
	private ContractEmployeeServiceImpl contractEmployeeServiceImpl = new ContractEmployeeServiceImpl();
	
	public EmployeeService createPermanentEmployeeInstance() {
		return permanentEmployeeServiceImpl;
	}
	
	public EmployeeService createContractEmployeeInstance() {
		return contractEmployeeServiceImpl;
	}
}

The basic idea of ServiceLocator class is to achieve loose coupling between objects and hide the object creation mechanism from the caller. 

The caller only knows what type of object you will return. You can alter the implementation of the PermanentEmployeeServiceImpl class or change the class itself to any new class implementation behind without affecting the caller functionalities.

Line 4 : permanentEmployeeServiceImpl instance variable to create and assign PermanentEmployeeServiceImpl object on demand. 

Line 5 : As like line 4 it will initialize ContractEmployeeServiceImpl instance to the instance variable.

Line 7 : createPermanentEmployeeInstance method will return the PermanentEmployeeServiceImpl object.

Line 11 : createContractEmployeeInstance method will return the CreateContractEmployeeInstance object.

Step 5 : Bean Definition

Create applicationContext.xml file under src folder and add the below code.

<?xml version="1.0" encoding="UTF-8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        
        <bean id="employeeController" class="net.geekcoders.controller.EmployeeController">
			<property name="employeeService" ref="permanentEmployee"></property>
        </bean>
        
        <bean id="employeeService" class="net.geekcoders.service.EmployeeServiceLocator"></bean>
        
        <bean id="permanentEmployee" factory-bean="employeeService" 
        	factory-method="createPermanentEmployeeInstance"></bean>
        
        <bean id="contractEmployee" factory-bean="employeeService" 
        	factory-method="createContractEmployeeInstance"></bean>
</beans>

Line 7 : Container will instantiate EmployeeController with employeeService bean object as a Dependency Setter Injection. 

Line 11: employeeService bean will create an instance of EmployeeServiceLocator Bean Object.

Line 13: permanentEmployee will refer to the employeeService bean and invoke createPermanentEmployeeInstance method of it and return the object reference what the method returns.

Line 16: contractEmployee will refer to the employeeService bean and invoke createContractEmployeeInstance method of it and return the object reference what the method returns.

Step 6 : EmployeeService interface

Create EmployeeService Interface under net.geekcoders.service package and add the below code.

package net.geekcoders.service;

import net.geekcoders.Employee;

public interface EmployeeService {
	boolean addNewEmployee(Employee employee);
}

This will group all the implementation classes.

Step 7 : PermanentEmployeeServiceImpl class

Create PermanentEmploueeServiceImpl class under net.geekcoders.service package and add below code.

package net.geekcoders.service;

import net.geekcoders.Employee;

public class PermanentEmployeeServiceImpl implements EmployeeService {

	public boolean addNewEmployee(Employee employee) {
		// Adds new permanent employee detail in Database.
		System.out.println("New Permanent Employee added Successfully");
		return true;
	}

}

The above method addNewEmployee will add new permanent employee details to DB.

Step 8 : ContractEmployeeServiceImpl class

Create ContractEmployeeServiceImpl class under net.geekcoders.service package and add below code.

package net.geekcoders.service;

import net.geekcoders.Employee;

public class ContractEmployeeServiceImpl implements EmployeeService {


	public boolean addNewEmployee(Employee employee) {
		// Adds new contract employee detail in Database.
		System.out.println("New Contract Employee added Successfully");
		return true;
	}
}

The above method addNewEmployee will add new contract employee details to DB.

Step 9 : Controller class

Create EmployeeController class under net.geekcoders.controller package and add below code. 

package net.geekcoders.controller;

import net.geekcoders.Employee;
import net.geekcoders.service.EmployeeService;

public class EmployeeController {
	private EmployeeService employeeService;
	private Employee employee;
	
	public void addNewEmployee() {
		this.getEmployeeService().addNewEmployee(employee);
	}

	public EmployeeService getEmployeeService() {
		return employeeService;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}
	
	public Employee getEmployee() {
		return employee;
	}
	
	public void setEmployee(Employee employee) {
		this.employee = employee;
	}
}

The above controller class is designed to accept Setter-Based dependency Injection.

Step 10 : Employee Class

Add Employee class to hold employee details to manipulate in service and controller classes.

package net.geekcoders;

public class Employee {
	private String name;
	private int age;
	private String role;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
}

Step 11 : Starter Class(Ioc Container)

Finally add Starter class to run the Spring Core application.

package net.geekcoders;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import net.geekcoders.controller.EmployeeController;

public class EmployeeStarter {
	
	public static void main(String args[]) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		EmployeeController controller = applicationContext.getBean("employeeController", EmployeeController.class);
		controller.addNewEmployee();
	}
	
}

If you run the program your Eclipse Console will print the message like below.

To make use of the other service locator Object with the above example program you can simply add another Bean Definition in the applicationContext.xml file. 

<bean id="contractEmployeeController" class="net.geekcoders.controller.EmployeeController">
			<property name="employeeService" ref="contractEmployee"></property>
        </bean>

To make use of the new Bean Definition contractEmployeeController you have to alter the EmployeeController class as like below. 

package net.geekcoders;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import net.geekcoders.controller.EmployeeController;

public class EmployeeStarter {
	
	public static void main(String args[]) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		EmployeeController controller = applicationContext.getBean("employeeController", EmployeeController.class);
		controller.addNewEmployee();//Invokes createPermanentServiceImpl method from EmployeeServiceLocator class.
		controller = applicationContext.getBean("contractEmployeeController", EmployeeController.class);
		controller.addNewEmployee();//Invokes createContractServiceImpl method from EmployeeServiceLocator class.
	}
	
}

Now run the program from EmployeeStarter class the IoC container will invoke both the ServiceLocator methods as per our request and prints in console as like below.

That’s all for now on Instance Factory method in Spring with Example.

Happy Reading!!!

Leave a Reply

Your email address will not be published. Required fields are marked *