Master Spring’s Core Design Patterns: The Interview‑Ready Answer That Stuns Recruiters
This article systematically breaks down the eight most common design patterns used inside the Spring framework, explains how the template pattern powers bean lifecycle, compares classic and Spring‑specific implementations, and provides concrete code examples and step‑by‑step walkthroughs to help you ace interview questions.
Eight design patterns commonly used in Spring
Template Method – used by JdbcTemplate, RestTemplate and the core bean‑creation process. The abstract class defines the invariant algorithm skeleton; subclasses or hook objects supply the variable steps.
Singleton – Spring beans are singletons by default; the container guarantees a single instance per bean definition.
Factory – BeanFactory and ApplicationContext act as factories that create and manage bean instances.
Proxy – Spring AOP creates dynamic proxies to weave cross‑cutting concerns such as logging and transaction management.
Strategy – HandlerMapping and HandlerAdapter are strategy interfaces that allow different request‑mapping algorithms.
Observer – Application events and listeners implement the observer pattern; the container notifies listeners when an event occurs.
Decorator – BeanPostProcessor chains decorate beans after their creation, adding behaviour without modifying the original class.
Adapter – HandlerAdapter adapts various controller types to a common processing interface.
Template Method pattern in Spring's bean lifecycle
In the classic template pattern an abstract class defines a template method that calls hook methods . Spring replaces hook methods with hook objects (e.g., InitializingBean, DisposableBean, @PostConstruct methods). The abstract class AbstractBeanFactory defines the fixed lifecycle steps, while the hook objects are supplied at runtime.
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. instantiate
Object bean = createBeanInstance(beanName, mbd, args);
// 2. populate properties
populateBean(beanName, mbd, instanceWrapper);
// 3. initialize (invoke hook objects)
bean = initializeBean(beanName, bean, mbd);
return bean;
}During initializeBean Spring invokes the following hook objects:
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
if (initMethodName != null && !(bean instanceof InitializingBean && "afterPropertiesSet".equals(initMethodName))) {
Method initMethod = ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName);
if (initMethod != null) {
ReflectionUtils.makeAccessible(initMethod);
ReflectionUtils.invokeMethod(initMethod, bean);
}
}This shows a stable skeleton (instantiation → property injection → initialization → destruction) with extensible hook points.
Key extension points in the bean lifecycle
BeanFactoryPostProcessor – modifies BeanDefinition objects before any bean is instantiated.
InstantiationAwareBeanPostProcessor – can replace a bean before instantiation or suppress property injection.
BeanPostProcessor – runs before and after initialization; commonly used for @Autowired processing and AOP proxy creation.
InitializingBean / @PostConstruct – custom logic after all properties have been set.
DisposableBean / @PreDestroy – cleanup logic before bean removal.
SmartInitializingSingleton – callback after all singleton beans have been created.
ApplicationContextAware – injects the ApplicationContext into a bean.
Practical example – connection‑pool warm‑up via BeanPostProcessor
The following BeanPostProcessor creates five connections for any DataSource bean after it has been initialized, eliminating the first‑request latency.
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Component
public class ConnectionPoolWarmerPostProcessor implements BeanPostProcessor {
private volatile boolean warmed = false;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DataSource && !warmed) {
synchronized (this) {
if (!warmed) {
warm((DataSource) bean);
warmed = true;
}
}
}
return bean;
}
private void warm(DataSource ds) {
System.out.println("🔥 Starting pool warm‑up...");
try {
for (int i = 0; i < 5; i++) {
Connection c = ds.getConnection();
c.close();
System.out.println("✅ Warmed connection #" + (i + 1));
}
} catch (SQLException e) {
System.err.println("⚠️ Warm‑up failed: " + e.getMessage());
}
}
}When the DataSource bean is created, Spring invokes postProcessAfterInitialization, the pool is warmed once, and subsequent requests can obtain a connection without the initial creation delay.
Summary
Spring heavily relies on classic design patterns. The Template Method pattern forms the backbone of the bean lifecycle: AbstractBeanFactory provides a fixed algorithm skeleton, while hook objects such as InitializingBean, DisposableBean, custom init/destroy methods, and various Aware interfaces allow developers to inject behaviour without modifying the core framework. Understanding these patterns and the associated extension points (e.g., BeanPostProcessor) enables precise customisation of bean creation, property injection, initialization and destruction, and is essential for both interview preparation and production‑grade Spring development.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tech Freedom Circle
Crazy Maker Circle (Tech Freedom Architecture Circle): a community of tech enthusiasts, experts, and high‑performance fans. Many top‑level masters, architects, and hobbyists have achieved tech freedom; another wave of go‑getters are hustling hard toward tech freedom.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
