How Spring Implements Classic Design Patterns: Factory, Singleton, and More

This article explains how Spring applies classic design patterns such as Simple Factory, Factory Method, Singleton, Adapter, Decorator, Proxy, Observer, Strategy, and Template Method, illustrating each pattern with implementation details, core code snippets, and their significance for loose coupling and extensibility in backend development.

Java Interview Crash Guide
Java Interview Crash Guide
Java Interview Crash Guide
How Spring Implements Classic Design Patterns: Factory, Singleton, and More

Simple Factory

Implementation

BeanFactory in Spring is an embodiment of the simple factory pattern. It returns a bean instance based on a unique identifier; creation may occur before or after the identifier is supplied depending on the situation.

Essence

A factory class decides which product class to create based on supplied parameters.

Implementation Details

Bean container startup phase:

Read bean XML configuration files and convert each bean element into a BeanDefinition object.

Register these BeanDefinitions with BeanFactory via BeanDefinitionRegistry, storing them in a ConcurrentHashMap.

After registration, Spring provides an extension point allowing custom code via BeanFactoryPostProcessor (e.g., PropertyPlaceholderConfigurer).

Bean instantiation phase:

Instantiation uses reflection or CGLIB. Spring exposes several extension points:

Aware interfaces (e.g., BeanFactoryAware) for injecting the BeanFactory instance.

BeanPostProcessor interface for invoking custom methods during bean creation.

InitializingBean interface for post‑initialization callbacks.

DisposableBean interface for cleanup when a bean is destroyed.

Design Significance

Loose coupling: Dependencies are injected through Spring’s BeanFactory, introducing a third party that resolves bean relationships.

Additional bean processing: By implementing Spring’s extension interfaces, developers can add custom behavior during the bean lifecycle.

Factory Method

Implementation

FactoryBean interface.

Implementation Details

Beans that implement FactoryBean are “factory beans”. When getBean() retrieves such a bean, Spring automatically calls its getObject() method, returning the object produced by getObject() rather than the factory bean itself.

Example

Typical example: integration of Spring with MyBatis.

Code example:

Explanation: Because the bean implements FactoryBean, the returned object is the result of SqlSessionFactoryBean.getObject(), not the SqlSessionFactoryBean instance itself.

Singleton Pattern

Spring’s default bean scope is singleton.

Dependency injection (including lazy‑init) occurs in AbstractBeanFactory.getBean, where doGetBean calls getSingleton to create the bean.

Key method analysis:

public Object getSingleton(String beanName) {
    // allow early reference
    return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

Process diagram: (illustrative image omitted)

Summary:

Singleton ensures a class has only one instance and provides a global access point.

Spring implements the second part by offering a global BeanFactory access point without enforcing constructor‑level singleton control.

Adapter Pattern

Implementation

Spring MVC’s HandlerAdapter.

Implementation Details

HandlerAdapter selects and executes the appropriate Handler based on defined rules.

Process

DispatcherServlet obtains a handler from HandlerMapping, then forwards the request to HandlerAdapter, which invokes the handler. After execution, the handler returns a ModelAndView to the adapter, which passes it back to DispatcherServlet.

Significance

HandlerAdapter simplifies extending handlers: adding a new handler only requires a corresponding adapter.

Decorator Pattern

Implementation

Spring uses wrapper classes (named *Wrapper* or *Decorator*) to add responsibilities dynamically.

Essence

Dynamically adds extra responsibilities to an object, offering more flexibility than subclassing.

Proxy Pattern

Implementation

AOP in Spring is built on dynamic proxy pattern.

Dynamic proxy: created at runtime without manual proxy class.

Static proxy: manually written proxy class that delegates to the target.

Implementation Details

Aspects are woven at runtime; the AOP container creates a proxy object for the target, and Spring AOP weaves the aspect into this proxy.

Weaving means applying an aspect to a target object and creating a new proxy.

Observer Pattern

Implementation

Spring’s event‑driven model uses the observer pattern; listeners implement ApplicationListener.

Components

Three parts: event source, event, and event listener.

(1) ApplicationEvent abstract class – extends java.util.EventObject; events inherit from it.

(2) ApplicationListener interface – extends java.util.EventListener; defines onApplicationEvent(E event).

(3) ApplicationContext interface – the global container that publishes events.

public abstract class ApplicationEvent extends EventObject {
    private static final long serialVersionUID = 7099057708183571937L;
    private final long timestamp;
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }
    public final long getTimestamp() {
        return this.timestamp;
    }
}
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    void onApplicationEvent(E event);
}
public interface ApplicationEventPublisher {
    void publishEvent(ApplicationEvent event);
}

Strategy Pattern

Implementation

Spring’s Resource interface abstracts various resource‑access strategies.

Resource Interface Overview

Key methods include getInputStream(), exists(), isOpen(), getDescription(), getFile(), getURL(). Different implementations (UrlResource, ClassPathResource, FileSystemResource, ServletContextResource, InputStreamResource, ByteArrayResource) handle specific resource types.

Template Method Pattern

Classic Definition

Superclass defines the skeleton; subclasses implement specific steps.

Spring’s Use

Spring combines template method with callback interfaces (e.g., JdbcTemplate).

Example

public abstract class JdbcTemplate {
    public final Object execute(String sql) {
        Connection con = null;
        Statement stmt = null;
        try {
            con = getConnection();
            stmt = con.createStatement();
            Object retValue = executeWithStatement(stmt, sql);
            return retValue;
        } catch (SQLException e) {
            // ...
        } finally {
            closeStatement(stmt);
            releaseConnection(con);
        }
    }
    protected abstract Object executeWithStatement(Statement stmt, String sql);
}

Callback interface:

public interface StatementCallback {
    Object doWithStatement(Statement stmt);
}

JdbcTemplate can execute a callback:

JdbcTemplate jdbcTemplate = ...;
final String sql = ...;
StatementCallback callback = new StatementCallback() {
    public Object doWithStatement(Statement stmt) {
        return ...;
    }
};
jdbcTemplate.execute(callback);

Using callbacks avoids subclassing for each variation.

backendTemplate MethodSingletonadapterFactoryObserver
Java Interview Crash Guide
Written by

Java Interview Crash Guide

Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.