How Spring Implements Classic Design Patterns: From Simple Factory to Template Method

This article explains how Spring’s core container uses classic design patterns—Simple Factory via BeanFactory, Factory Method with FactoryBean, Singleton, Adapter, Decorator, Proxy, Observer, Strategy, and Template Method—illustrated with code snippets and diagrams to show their implementation and purpose within the framework.

Java Interview Crash Guide
Java Interview Crash Guide
Java Interview Crash Guide
How Spring Implements Classic Design Patterns: From Simple Factory to Template Method

Simple Factory (not one of the 23 design patterns)

Implementation: BeanFactory. In Spring, BeanFactory embodies the simple factory pattern, returning a Bean object based on a unique identifier; creation timing depends on the specific scenario.

Essence: a factory class decides which product class to instantiate based on input parameters.

Implementation principle

Bean container startup phase

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

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

After registration, developers can insert custom code by implementing BeanFactoryPostProcessor (e.g., PropertyPlaceholderConfigurer for datasource placeholders).

Bean instantiation phase

Beans are instantiated via reflection or CGLIB.

Spring provides many extension points: BeanFactoryAware – injects the BeanFactory instance. BeanPostProcessor – allows custom processing before and after bean initialization. InitializingBean – callback after properties are set. DisposableBean – callback before bean destruction.

Design significance

Loose coupling: dependencies are injected by the BeanFactory instead of hard‑coded.

Extra bean handling: implementing specific interfaces lets Spring invoke custom logic during the bean lifecycle.

Factory Method

Implementation: FactoryBean interface.

Principle: a bean that implements FactoryBean is a factory; when getBean() is called, Spring invokes its getObject() and returns that object instead of the factory itself.

Example: Spring‑MyBatis integration where SqlSessionFactoryBean implements FactoryBean and returns a SqlSessionFactory instance.

Singleton Pattern

Spring’s default bean scope is singleton, meaning one instance per container.

Spring creates singletons in AbstractBeanFactory.getBean() via getSingleton(), which uses double‑checked locking to ensure thread‑safe lazy initialization.

public Object getSingleton(String beanName){
    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);
}

Diagram: (image omitted for brevity)

Adapter Pattern

Implementation: Spring MVC’s HandlerAdapter.

Principle: HandlerAdapter selects the appropriate handler based on the request, invokes it, and returns a ModelAndView to the DispatcherServlet.

Decorator Pattern

Implementation in Spring appears as classes whose names contain Wrapper or Decorator.

Essence: dynamically add responsibilities to an object; more flexible than subclassing.

Proxy Pattern

Implementation: Spring AOP uses dynamic proxying.

Dynamic proxy: created at runtime without manual proxy class; static proxy requires a hand‑written class.

Principle: when a proxy is created, method calls are intercepted and delegated to the target object, enabling cross‑cutting concerns.

Observer Pattern

Implementation: Spring’s event‑driven model.

Core components: ApplicationEvent (event), ApplicationListener (listener), and ApplicationContext (event source).

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 for resource access.

Key methods: getInputStream(), exists(), isOpen(), getDescription(), getFile(), getURL().

Concrete implementations include UrlResource, ClassPathResource, FileSystemResource, ServletContextResource, InputStreamResource, and ByteArrayResource.

Template Method Pattern

Definition: the abstract class defines the skeleton of an algorithm; subclasses provide concrete implementations for specific steps.

Spring uses this pattern extensively, e.g., JdbcTemplate and its callback mechanism.

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;
        }finally{
            closeStatement(stmt);
            releaseConnection(con);
        }
    }
    protected abstract Object executeWithStatement(Statement stmt, String sql);
}

Callback interface:

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

Using the callback:

public final Object execute(StatementCallback callback){
    Connection con = null;
    Statement stmt = null;
    try{
        con = getConnection();
        stmt = con.createStatement();
        Object retValue = callback.doWithStatement(stmt);
        return retValue;
    }finally{
        closeStatement(stmt);
        releaseConnection(con);
    }
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

springTemplate MethodSingletonFactory MethodBeanFactory
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.