January 20, 2021
Hot Topics:

Define Factories in Spring XML Using Method Injection

  • By Shekhar Gulati
  • Send Email »
  • More Articles »

Sometimes in Spring-based applications I need to define conditional beans. For example, suppose I need to define an image service such that depending on the image type provided it chooses an appropriate reader (i.e. if the image type is JPEG it will use JpegReader and if the image type is GIF it will use GifReader). To create such a service, I can create a factory that encapsulates the details of object creation and the service will return the required reader for the given reader type. In a factory, instances are created manually using the new operator.

In this article, I demonstrate how to define factories in XML using method injection and ServiceLocatorFactoryBean. I use the image service as the demo application, an application in which all the beans are created and wired using a dependency injection container like Spring and a factory in which I manually create the beans. Specifically, I will create a SimpleImageFactory (see below), which depending on the image type will return the correct image reader.

import com.shekhar.image.ImageType;

public class SimpleImageReaderFactory implements ReadersFactory {

public ImageReader getReader(ImageType imageType) {
switch (imageType) {
case GIF:
return new GifReader();
case JPEG:
return new JpegReader();
return new DefaultReader();

I have an ImageService, which will have a SimpleImageFactory injected into it. The factory can be injected into the service using a dependency injection container like Spring, or it can be used directly in the code.

 public class ImageService implements Service {

private ReadersFactory factory;

public ImageService(ReadersFactory factory) {
this.factory = factory;

* Reads image for {@link InputStream} for a given image type
public Image readImage(InputStream in) {
ImageType imageType = getImageType(in);
ImageReader reader = factory.getReader(imageType);
Image image = reader.read(in);
return image;

private ImageType getImageType(InputStream in) {
return ImageType.GIF;


This is the easiest approach to implement the factory but it has a few limitations:

  1. This approach leads to tight coupling, as I am manually creating the objects.
  2. This approach leads to boilerplate code of creating new instances and returning the beans based on the type.
  3. This approach does not use a dependency injection container like Spring to manage my beans. So, I am not making full use of Spring.

To remove some of these limitations I can use method injection.

Using a Factory with Method Injection

A better approach could be to use the power of method injection in my factory. Method injection allows a container to inject methods instead of objects and provides dynamic sub-classing. In other words, method injection provides a mechanism by which you can inject objects in your factory methods. To make this approach more concrete, I will apply this to my existing solution of using a simple factory.

ImageService will have an ImageReaderFactory (see below), which again is injected into the service using a dependency injection container like Spring.

public abstract class ImageReaderFactory implements ReadersFactory {

public ImageReader getReader(ImageType imageType) {
switch (imageType) {
case GIF:
return getGifReader();
case JPEG:
return getJpegReader();
return getDefaultReader();

protected abstract ImageReader getGifReader();

protected abstract ImageReader getJpegReader();

protected abstract ImageReader getDefaultReader();

ImageReaderFactory is an abstract class with three abstract methods: getJpegReader(), getGifReader(), and getDefaultReader().The Spring Framework implements this method injection by dynamically generating a subclass and overriding the method, using bytecode generation via the CGLIB library. The method to be 'injected' must have the following signature.

[abstract] theMethodName(no-arguments);

The method does not have to be abstract, but even if you make it non-abstract, the dynamically created class will override the concrete method provided in the class. You need to define the following in your Spring context file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"

<bean id="serviceWithFactory" class="com.shekhar.service.ImageService">
<ref bean="imageReaderFactory" />

<bean id="jpegReader" class="com.shekhar.reader.JpegReader" scope="prototype" />

<bean id="gifReader" class="com.shekhar.reader.GifReader" scope="prototype" />

<bean id="defaultReader" class="com.shekhar.reader.DefaultReader"
scope="prototype" />

<bean id="imageReaderFactory" class="com.shekhar.reader.ImageReaderFactory">
<lookup-method bean="jpegReader" name="getJpegReader" />
<lookup-method bean="gifReader" name="getGifReader" />
<lookup-method bean="defaultReader" name="getDefaultReader" />


The Pro and Cons of Using Method Injection

The method injection approach has an advantage over writing a simple factory: the beans are managed by the dependency injection container and you do not create the new instances in your code manually. The beans gifReader, jpegReader, and defaultReader are prototype because they might be stateful.

On the other hand, using method injection has its advantages as well:

  1. You still have to write a factory class, and method injection relies on creating class proxies for which you have to add a cglib-nodep dependency (if you don't have it already) in your application.
  2. The method to be injected has to be a no argument method (i.e. you can't pass any parameters to it).

To remove these limitations, I use the power of Spring ServiceLocatorFactoryBean, which provides the best solution to implement such conditional factories.

Originally published on https://www.developer.com.

Page 1 of 2

This article was originally published on April 4, 2011

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date