Showing posts with label Factory Design Pattern. Show all posts
Showing posts with label Factory Design Pattern. Show all posts

Tuesday, 31 July 2018

What is Spring DI with a static factory method that returns the instance of another class?

Enjoying This Tutorial?

Subscribe to Ram N Java for high-quality, practical Java and Spring tutorials!

SUBSCRIBE NOW

Introduction

In Spring XML configuration, the IoC container can create beans not only by invoking constructors or static methods of the same class, but also by invoking a static factory method located on a completely different class. This capability is widely used when working with legacy factory utility classes, third-party libraries, or complex factory design patterns.

Why Use a Static Factory Method of Another Class?

  • Factory Separation: Keeps product classes clean and stateless while delegating construction logic to a separate static factory class.
  • Third-Party Integration: Allows Spring to manage objects instantiated by external factories without needing modifications to their source code.
  • Simple XML Configuration: Uses the class attribute to specify the factory class and factory-method to specify the static method returning the target object.

Step-by-Step Configuration Example

Consider a scenario where a separate class, BeanFactory, contains a static method to produce instances of Printer:

1. The Factory and Product Classes

package com.ram.factory;

import com.ram.service.Printer;

public class BeanFactory {
    // Static factory method returning an instance of another class
    public static Printer getPrinterInstance() {
        return new Printer();
    }
}

2. Configuring in applicationContext.xml

The class attribute points to the factory class, while factory-method invokes the static method:

<!-- Bean created by calling a static method on BeanFactory -->
<bean id="printer" 
      class="com.ram.factory.BeanFactory" 
      factory-method="getPrinterInstance" />

3. Retrieving the Bean in Java

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Printer printer = (Printer) context.getBean("printer");
printer.print();

Key Takeaway

When you specify class and factory-method, Spring calls that static method to obtain the resulting bean instance. The bean registered in the container is the object returned by the factory method, not the factory class itself.


Click here to watch on Youtube:
https://www.youtube.com/watch?v=C1KrLW_c0pk&list=UUhwKlOVR041tngjerWxVccw

Click the below Image to Enlarge:
What is Spring DI with a static factory method that returns the instance of another class?

What is Spring DI with a static factory method that returns the instance of another class?

What is Spring DI with a static factory method that returns the instance of another class?


pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ram.core</groupId>
    <artifactId>SpringDemo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>SpringDemo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <spring.version>5.0.2.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <!-- Spring 5 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

Animal.java

package com.ram.model;

public interface Animal
{
    public abstract void eat();
}

Cow.java

package com.ram.model;

public class Cow implements Animal
{

    public void eat()
    {
        System.out.println("Cow eats grass..");
    }

}

Dog.java

package com.ram.model;

public class Dog implements Animal
{

    public void eat()
    {
        System.out.println("Dog eats chicken bone...");
    }

}

AnimalFactory.java

package com.ram.factory;

import com.ram.model.Animal;
import com.ram.model.Dog;

public class AnimalFactory
{
    public static Animal getAnimal()
    {
        return new Dog();// return any one instance, either Dog or Cow
        // return new Cow();
    }
}

applicationContext.xml

<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-4.3.xsd">


    <bean id="animal" class="com.ram.factory.AnimalFactory"
        factory-method="getAnimal">
    </bean>

</beans>


App.java

package com.ram.core;

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

import com.ram.model.Animal;

public class App
{
    public static void main(String[] args)
    {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");

        System.out.println("---------------------------------------");

        Animal animal = (Animal)context.getBean("animal");
        System.out.println(
                "Got " + animal +" object from the ApplicationContext[Spring Container]");
       
        animal.eat();
    }

}

Output

Jul 05, 2018 9:24:36 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5b37e0d2: startup date [Thu Jul 05 09:24:36 IST 2018]; root of context hierarchy
Jul 05, 2018 9:24:36 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
---------------------------------------
Got com.ram.model.Dog@3ffc5af1 object from the ApplicationContext[Spring Container]
Dog eats chicken bone...

Click the below link to download the code:
https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_DI_StaticfactoryMethod_another_class.zip?attredirects=0&d=1

Github Link:
https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_DI_StaticfactoryMethod_another_class

Bitbucket Link:
https://bitbucket.org/ramram43210/spring/src/87c44fe2f8e6bec23f023e02860b09f4be9b1bfd/Spring_2018/SpringDemo_DI_StaticfactoryMethod_another_class/?at=master

See also:

  • All JavaEE Videos Playlist
  • All JavaEE Videos
  • All JAVA EE Links
  • Spring Tutorial
  • Servlets Tutorial
  • All Design Patterns Links
  • JDBC Tutorial
  • Java Collection Framework Tutorial
  • JAVA Tutorial
  • Kids Tutorial
  • Cooking Tutorial
  • Tutorials