Design pattern are widely used in software design. One of the most famous patterns is the Abstract Factory. In this article we will see how to implement and Abstract Factory pattern with Spring.
Basically this pattern is made by:
- an abstract factory class that define the contract of the factory
- some concrete factory classes that implements the abstract factory class and instantiate the resources
- some abstract resources
- their concrete classes
In Spring every bean is a singleton by default in the IoC Container. What we want is a new resource instance of a prototype bean at runtime more than once.
Spring beans dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.
However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.
What we need is Spring lookup method injection. Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container.
We can use Spring to define our concrete factory classes. Letโs how.
Resources
First, we define our abstract resources
public interface IResourceA { public void doResourceAStuff(); } public interface IResourceB { public void doResourceBStuff(); }
and one concrete class for each of them.
public class ResourceA implements IResourceA { public void doResourceAStuff() { System.out.println("Do resource A stuff"); } } public class ResourceB implements IResourceB { public void doResourceBStuff() { System.out.println("Do resource B stuff"); } }
The Abstract Factory pattern requires that there are several concrete classes for every abstract resource.
Of course, you can define all abstract resources you want.
AbstractClass
Now, itโs time for the AbstractClass.
public abstract class AbstractFactory { public abstract IResourceA getResourceA(); public abstract IResourceB getResourceB(); }
Spring configuration
You can put these lines in your applicationContex.xml file.
<bean id="resourceA" class="org.madbit.spring.resource.ResourceA" scope="prototype" /> <bean id="resourceB" class="org.madbit.spring.resource.ResourceB" scope="prototype" /> <bean id="factory" class="org.madbit.spring.factory.AbstractFactory" > <lookup-method name="getResourceA" bean="resourceA"/> <lookup-method name="getResourceB" bean="resourceB"/> </bean>
Lookup-method names must be the same used for methods defined in AbstractFactory class. Here you you can define all (concrete) factory declaration you need.
Client
Now we can implement a simple client that user:
public class MyClient { @Autowired private AbstractFactory abstractFactory; public void doStuff(HttpServletRequest req, HttpServletResponse res) throws IOException { IResourceA resourceA = abstractFactory.getResourceA(); IResourceB resourceB = abstractFactory.getResourceB(); resourceA.doResourceAStuff(); resourceB.doResourceBStuff(); } }
If you want use @Autowired annotation, remember to enable it putting the following configuration in you applicationContext.xml:
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />