# What Are Design Patterns and How Are They Applied in Spring?

> Explore design patterns and see how Spring applies key solutions like IoC Factory Singleton Proxy and more to build flexible maintainable enterprise Java applications. Learn to code smarter.

- Repository: [Guide/JavaGuide](https://github.com/Snailclimb/JavaGuide)
- Tags: deep-dive
- Published: 2026-02-24

---

**Design patterns are reusable solutions to common software design problems, and the Spring Framework implements patterns such as Inversion of Control, Factory, Singleton, Proxy, Template Method, Observer, Adapter, and Decorator to provide a flexible, maintainable, and testable enterprise Java architecture.**

Design patterns capture proven best-practice structures, interactions, and responsibilities that help developers build **flexible**, **maintainable**, and **testable** systems. According to the JavaGuide repository, the Spring Framework heavily relies on these patterns to deliver core features such as **Inversion of Control (IoC)**, **Dependency Injection (DI)**, **Aspect-Oriented Programming (AOP)**, and **event handling**. Understanding how Spring applies these patterns—as documented in [`docs/system-design/framework/spring/spring-design-patterns-summary.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md)—is essential for writing idiomatic Spring code.

## Inversion of Control and Dependency Injection

The **Inversion of Control (IoC)** pattern decouples components so that they do not create their own dependencies. Spring implements this through **Dependency Injection (DI)**, where the IoC container creates beans and injects them into dependent objects via `@Autowired`, XML configuration, or Java-based configuration.

In [`docs/system-design/framework/spring/spring-design-patterns-summary.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md), the repository explains that this pattern is the foundation of Spring's architecture, allowing the framework to manage component wiring through the `BeanFactory` and `ApplicationContext` containers.

```java
@Configuration
public class AppConfig {
    @Bean               // Spring’s factory method
    public Service myService(Repository repo) {
        return new ServiceImpl(repo);
    }

    @Bean
    public Repository repo() {
        return new JdbcRepository();   // concrete implementation hidden from the caller
    }
}

```

The `@Bean` methods act as a factory, while Spring automatically handles the injection of the `Repository` dependency into `myService`.

## Factory Pattern

Spring leverages the **Factory Pattern** to centralize object creation, allowing for interchangeable implementations and lazy loading. The `BeanFactory` and `ApplicationContext` interfaces serve as factories that instantiate and configure beans according to their definitions.

According to the JavaGuide documentation, this abstraction allows Spring to manage the complete lifecycle of objects without the calling code being aware of the concrete classes being instantiated.

## Singleton Pattern

By default, Spring manages beans as **Singletons**, ensuring that only one shared instance exists per container for heavy-weight resources such as thread pools, caches, and database connection pools.

As detailed in [`docs/system-design/framework/spring/spring-design-patterns-summary.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md), Spring registers each singleton bean in a `ConcurrentHashMap` called `singletonObjects`. The default scope for every bean is *singleton*, though this can be overridden with `@Scope("prototype")` or other scope definitions.

```java
@Service
public class CacheService {
    // Only one instance per Spring container
}

// Retrieving the bean twice yields the same object
CacheService a = ctx.getBean(CacheService.class);
CacheService b = ctx.getBean(CacheService.class);
assert a == b;   // true – singleton semantics

```

## Proxy Pattern

Spring implements the **Proxy Pattern** to enable method-level interception for cross-cutting concerns such as transactions, security, and logging. Through **Aspect-Oriented Programming (AOP)**, Spring creates JDK dynamic proxies for interface-based beans or CGLIB subclasses for concrete classes.

The JavaGuide repository notes that this dynamic proxy mechanism allows Spring to wrap target objects transparently, adding behavior before and after method execution without modifying the original source code.

```java
@Service
public class OrderService {
    @Transactional               // Spring creates a proxy around this method
    public void placeOrder(Order o) {
        // business logic
    }
}

```

Spring generates a runtime proxy that starts a transaction before `placeOrder` executes and commits or rolls back after it returns.

## Template Method Pattern

The **Template Method Pattern** provides a fixed workflow while allowing subclasses or callbacks to customize specific steps. Spring applies this pattern extensively in its `*Template` classes such as `JdbcTemplate`, `HibernateTemplate`, and `RestTemplate`.

As documented in the repository, these template classes define the algorithm skeleton—including resource acquisition, exception handling, and cleanup—while client code supplies callbacks to handle specific data mapping or business logic.

```java
@Autowired
private JdbcTemplate jdbcTemplate;

public List<User> findAll() {
    String sql = "SELECT * FROM users";
    return jdbcTemplate.query(sql, (rs, rowNum) -> 
        new User(rs.getLong("id"), rs.getString("name")));
}

```

`JdbcTemplate` defines the overall query-execution algorithm, while the lambda supplies the row-mapping step.

## Observer Pattern

Spring utilizes the **Observer Pattern** to facilitate loosely coupled event publishing and handling. Through the `ApplicationEvent` and `ApplicationListener` mechanism, components can broadcast events to all registered listeners without direct coupling between publisher and consumer.

According to [`docs/system-design/framework/spring/spring-design-patterns-summary.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md), this event-driven model supports both synchronous and asynchronous event processing, making it ideal for implementing domain events and cross-cutting notifications.

```java
// Event definition
public class OrderCreatedEvent extends ApplicationEvent {
    private final Order order;
    public OrderCreatedEvent(Object source, Order order) {
        super(source);
        this.order = order;
    }
    public Order getOrder() { return order; }
}

// Listener
@Component
public class NotificationListener implements ApplicationListener<OrderCreatedEvent> {
    @Override
    public void onApplicationEvent(OrderCreatedEvent e) {
        // react to the event
        System.out.println("Order created: " + e.getOrder().getId());
    }
}

// Publisher
@Component
public class OrderService {
    @Autowired ApplicationEventPublisher publisher;
    public void create(Order o) {
        // persist order …
        publisher.publishEvent(new OrderCreatedEvent(this, o));
    }
}

```

## Adapter Pattern

The **Adapter Pattern** allows incompatible interfaces to work together without modifying either side. Spring employs this pattern in multiple subsystems, most notably in Spring MVC’s `HandlerAdapter` and AOP’s `AdvisorAdapter`.

As detailed in the JavaGuide repository, `HandlerAdapter` adapts various controller types to a common invocation contract, while `AdvisorAdapter` adapts different advice types to the `MethodInterceptor` interface. This decouples the framework's core dispatcher from specific controller implementations.

```java
@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello() { return "hello"; }
}
// Internally, DispatcherServlet uses a HandlerAdapter to invoke the above method,
// decoupling the servlet from the concrete controller class.

```

## Decorator Pattern

Spring applies the **Decorator Pattern** (also known as the Wrapper Pattern) to add responsibilities to objects dynamically without subclassing. This is evident in DataSource wrappers, `HttpMessageConverter` chains, and various `*Wrapper` classes throughout the framework.

According to the repository documentation, these decorators augment behavior at runtime while maintaining the same interface, allowing for transparent enhancement of core functionality such as connection pooling, logging, and transaction management.

```java
@Bean
public DataSource dataSource() {
    HikariDataSource ds = new HikariDataSource();
    ds.setJdbcUrl("jdbc:h2:mem:test");
    // Wrap with a proxy that adds logging
    return new LoggingDataSource(ds);
}

```

`LoggingDataSource` implements `DataSource` and delegates calls to the underlying Hikari instance, adding extra behaviour.

## Key Files in the JavaGuide Repository

The following files in the Snailclimb/JavaGuide repository provide detailed explanations and source references for the patterns discussed above:

| File | Purpose | Link |
|------|---------|------|
| [`docs/system-design/framework/spring/spring-design-patterns-summary.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md) | Full narrative of each Spring‑related pattern (factory, singleton, proxy, template, observer, adapter, decorator, etc.) | [View File](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md) |
| [`docs/system-design/design-pattern.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/design-pattern.md) | General overview of design‑pattern interview topics | [View File](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/design-pattern.md) |
| [`docs/java/basis/proxy.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/java/basis/proxy.md) | Stand‑alone explanation of the Proxy pattern | [View File](https://github.com/Snailclimb/JavaGuide/blob/main/docs/java/basis/proxy.md) |
| [`docs/java/io/io-design-patterns.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/java/io/io-design-patterns.md) | Illustrates Decorator & Adapter patterns in core Java I/O | [View File](https://github.com/Snailclimb/JavaGuide/blob/main/docs/java/io/io-design-patterns.md) |

## Summary

- **Design patterns** provide reusable solutions to common software design problems, capturing proven structures for flexible and maintainable code.
- **Inversion of Control** and **Dependency Injection** form the architectural foundation of Spring, decoupling components through container-managed bean creation and wiring.
- **Factory Pattern** appears in `BeanFactory` and `ApplicationContext`, centralizing object creation and supporting lazy initialization.
- **Singleton Pattern** is the default bean scope, with instances stored in a `ConcurrentHashMap` called `singletonObjects` to ensure single instances per container.
- **Proxy Pattern** enables **AOP** through JDK dynamic proxies or CGLIB subclasses, supporting cross-cutting concerns like transactions and security.
- **Template Method Pattern** appears in `JdbcTemplate` and similar classes, defining algorithm skeletons while allowing custom callbacks.
- **Observer Pattern** drives Spring's event system through `ApplicationEvent` and `ApplicationListener` for loose coupling between publishers and consumers.
- **Adapter Pattern** allows Spring MVC to support multiple controller types via `HandlerAdapter` and AOP to adapt various advice types to `MethodInterceptor`.
- **Decorator Pattern** adds dynamic behavior to objects, seen in DataSource wrappers and message converter chains, without modifying original classes.

## Frequently Asked Questions

### What is the most important design pattern used in Spring?

**Inversion of Control (IoC)** and **Dependency Injection (DI)** are the foundational patterns that make Spring distinct. These patterns decouple object creation from business logic, allowing the framework to manage component wiring through the `BeanFactory` and `ApplicationContext` containers, as detailed in [`docs/system-design/framework/spring/spring-design-patterns-summary.md`](https://github.com/Snailclimb/JavaGuide/blob/main/docs/system-design/framework/spring/spring-design-patterns-summary.md).

### How does Spring implement the Singleton pattern?

Spring implements the **Singleton Pattern** by default for all beans, storing each instance in a `ConcurrentHashMap` named `singletonObjects` within the IoC container. This ensures that only one shared instance exists per container for heavy-weight resources, though developers can override this with `@Scope("prototype")` or other scope definitions when multiple instances are required.

### What is the difference between JDK dynamic proxy and CGLIB in Spring AOP?

Spring uses **JDK dynamic proxies** when the target bean implements at least one interface, creating a proxy that implements the same interfaces. For concrete classes without interfaces, Spring falls back to **CGLIB** to generate a subclass proxy. Both approaches allow method interception for cross-cutting concerns like transactions and security without modifying the original source code.

### When should I use the Template Method pattern in Spring?

Use the **Template Method Pattern** when you need to execute a standard workflow—such as database access, JMS messaging, or REST communication—while varying specific steps like result mapping or error handling. Spring's `JdbcTemplate`, `HibernateTemplate`, and `RestTemplate` classes embody this pattern by handling resource management, exception translation, and cleanup, while you supply callbacks or lambdas for custom logic.