Backend Development 17 min read

Common Design Patterns Used in the Spring Framework

This article reviews the most frequently applied design patterns in Spring—including IoC/DI, Factory, Singleton, Proxy (AOP), Template Method, Observer, Adapter, and Decorator—explaining their purpose, how Spring implements them, and providing concise code examples for each.

Java Captain
Java Captain
Java Captain
Common Design Patterns Used in the Spring Framework

Design patterns represent proven object‑oriented programming practices, and the Spring framework extensively applies many of them. This article summarizes the key patterns you are likely to encounter during Spring development and interview preparation.

Inversion of Control (IoC) and Dependency Injection (DI)

IoC is a principle, not a pattern, that decouples objects by delegating their creation and wiring to the Spring IoC container. DI is the concrete pattern that injects dependencies into beans, turning object creation from an active to a passive process.

Factory Pattern

Spring creates beans via the BeanFactory or ApplicationContext . The latter is a richer container that eagerly instantiates all singleton beans, while BeanFactory performs lazy injection and uses less memory.

Key ApplicationContext implementations:

ClassPathXmlApplicationContext – loads configuration from the classpath.

FileSystemXmlApplicationContext – loads XML from the file system.

XmlWebApplicationContext – loads XML in a web environment.

Example of creating a bean with FileSystemXmlApplicationContext :

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

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new FileSystemXmlApplicationContext(
                "C:/work/IOC Containers/springframework.applicationcontext/src/main/resources/bean-factory-config.xml");
        HelloApplicationContext obj = (HelloApplicationContext) context.getBean("helloApplicationContext");
        obj.getMsg();
    }
}

Singleton Pattern

Spring beans are singleton by default. Besides singleton , Spring supports prototype , request , session , and (historically) global-session scopes. Singleton beans are registered in a thread‑safe ConcurrentHashMap inside the container.

// Simplified singleton registry implementation
private final Map
singletonObjects = new ConcurrentHashMap<>(64);

public Object getSingleton(String beanName, ObjectFactory
singletonFactory) {
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            try {
                singletonObject = singletonFactory.getObject();
            } catch (Exception ex) { /* omitted */ }
            addSingleton(beanName, singletonObject);
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
    }
}

Proxy (AOP) Pattern

Spring AOP relies on dynamic proxies. If a target implements an interface, Spring uses JDK dynamic proxies; otherwise it falls back to CGLIB to create a subclass proxy. This enables cross‑cutting concerns such as transaction management, logging, and security.

Template Method Pattern

Classes like JdbcTemplate and HibernateTemplate follow the template method pattern, defining the algorithm skeleton while delegating specific steps to callbacks. Spring combines this with the Callback pattern to achieve reusable, flexible data‑access code.

public abstract class Template {
    public final void templateMethod() {
        primitiveOperation1();
        primitiveOperation2();
        primitiveOperation3();
    }
    protected void primitiveOperation1() { /* default */ }
    protected abstract void primitiveOperation2();
    protected abstract void primitiveOperation3();
}

public class TemplateImpl extends Template {
    @Override
    public void primitiveOperation2() { /* implementation */ }
    @Override
    public void primitiveOperation3() { /* implementation */ }
}

Observer Pattern

Spring’s event‑driven model is a classic observer implementation. An ApplicationEvent represents the subject, ApplicationListener is the observer, and ApplicationEventPublisher publishes events to registered listeners.

package org.springframework.context;

@FunctionalInterface
public interface ApplicationListener
extends EventListener {
    void onApplicationEvent(E event);
}

Typical usage involves defining a custom event, a listener that implements ApplicationListener , and a publisher that calls applicationContext.publishEvent(new DemoEvent(this, "msg")) .

Adapter Pattern

Spring AOP’s advice types (e.g., BeforeAdvice , AfterReturningAdvice ) are adapted to the common MethodInterceptor interface via adapters such as MethodBeforeAdviceInterceptor . In Spring MVC, HandlerAdapter adapts various controller types to a uniform handling contract.

Decorator (Wrapper) Pattern

Many JDK I/O classes (e.g., BufferedInputStream ) and Spring’s data‑source wrappers illustrate the decorator pattern, allowing additional responsibilities to be added to objects without modifying their core code.

Summary of Patterns Used in Spring

Factory Pattern – bean creation via BeanFactory / ApplicationContext .

Proxy Pattern – core of Spring AOP.

Singleton Pattern – default bean scope.

Template Method Pattern – JdbcTemplate , HibernateTemplate , etc.

Decorator (Wrapper) Pattern – dynamic data‑source handling.

Observer Pattern – Spring event model.

Adapter Pattern – AOP advice adapters and MVC HandlerAdapter .

Design PatternsaopIoCspringDependency InjectionSingletonFactory
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login 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.