Which design patterns are most heavily used in Spring?
A strong answer is:
- Singleton – default bean scope
- Factory – BeanFactory/ApplicationContext
- Proxy – AOP, Transactions, Security, Caching
- Template Method – JdbcTemplate, RestTemplate
- Strategy – Multiple bean implementations
- Observer – Event publishing and listeners
- Adapter – Spring MVC HandlerAdapter
- Facade – Simplified access to complex frameworks
How does Spring use design patterns Internally?
1. Singleton Pattern — How Spring Actually Uses It
What developers see
@Service
public class UserService {
}
@Autowired
private UserService userService;
Every injection gets the same instance.
What happens internally
During application startup:
Spring Container Starts
↓
Scans Classes
↓
Creates Bean Definitions
↓
Creates Singleton Objects
↓
Stores Them in Cache
Internally Spring maintains a singleton cache (simplified):
Map<String, Object> singletonObjects;
Example:
"userService" → UserService@123
"orderService" → OrderService@456
When code asks for:
context.getBean("userService");
Spring checks:
if(beanExistsInCache){
return existingBean;
}
instead of:
new UserService();
Why Spring uses Singleton
Imagine:
1000 requests
Without Singleton:
1000 UserService objects
With Singleton:
1 UserService object
Less memory and faster creation.
2. Factory Pattern — How Spring Uses It
The IoC container is essentially a giant factory.
Instead of:
UserService service =
new UserService();
you ask Spring:
UserService service =
context.getBean(UserService.class);
Internal Flow
Suppose:
@Service
public class UserService {
}
Spring creates metadata:
Bean Name = userService
Class = UserService
Scope = Singleton
Stored as:
BeanDefinition
When requested:
context.getBean(UserService.class);
Spring executes:
createBean()
internally.
Simplified:
Object createBean(Class clazz){
return clazz.newInstance();
}
This is Factory Pattern.
Real Spring Classes
BeanFactory
ApplicationContext
DefaultListableBeanFactory
These are all factory implementations.
3. Dependency Injection — How It Works
Consider:
@Service
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService){
this.paymentService = paymentService;
}
}
What Spring Does
Step 1:
Find bean:
PaymentService
Create object:
PaymentService payment =
new PaymentService();
Step 2:
Create:
OrderService
and inject dependency:
new OrderService(payment);
Dependency Graph
OrderService
↓
PaymentService
↓
DatabaseService
Spring resolves the graph automatically.
Why This Matters
Without DI:
OrderService
creates
PaymentService
Tight coupling.
With DI:
Spring
creates
everything
Loose coupling.
4. Proxy Pattern — The Most Important Spring Pattern
Interviewers love this one.
Example
@Transactional
public void transferMoney() {
withdraw();
deposit();
}
You think:
transferMoney()
is called directly.
Actually:
Client
↓
Proxy
↓
Actual Service
Internal Flow
Spring creates:
AccountServiceProxy
around:
AccountService
Generated dynamically using:
JDK Dynamic Proxy
or
CGLIB
Simplified Proxy
Real service:
class AccountService {
void transferMoney() {
// business logic
}
}
Proxy:
class AccountServiceProxy {
AccountService target;
void transferMoney() {
startTransaction();
try {
target.transferMoney();
commit();
}
catch(Exception e){
rollback();
}
}
}
What Happens At Runtime
accountService.transferMoney();
Actually executes:
proxy.transferMoney();
which then calls:
real.transferMoney();
Why Spring Uses Proxy
To add functionality without changing business code.
Examples:
@Transactional
@Cacheable
@Async
@PreAuthorize
All rely on proxies.
5. Template Method Pattern — JdbcTemplate
Before Spring:
Connection conn = null;
try{
conn = getConnection();
PreparedStatement stmt =
conn.prepareStatement(sql);
ResultSet rs =
stmt.executeQuery();
}
finally{
closeEverything();
}
Every DAO repeats this code.
Spring Solution
jdbcTemplate.query(
sql,
rowMapper
);
Internal Algorithm
Spring controls:
Open Connection
↓
Prepare Statement
↓
Execute Query
↓
Handle Exceptions
↓
Close Resources
You provide only:
RowMapper
Example:
(rs,rowNum)-> new User(
rs.getLong("id"),
rs.getString("name")
)
Why Template Method
Framework controls the algorithm.
Developer fills customizable steps.
6. Strategy Pattern — How Spring Uses It
Imagine:
Credit Card
PayPal
UPI
Crypto
Interface:
public interface PaymentStrategy {
void pay();
}
Implementations:
@Component
class CreditCardPayment
@Component
class PaypalPayment
Spring registers all:
creditCardPayment
paypalPayment
Inject specific strategy:
@Qualifier("paypalPayment")
PaymentStrategy strategy;
Runtime behavior changes simply by changing bean selection.
No:
if(paymentType.equals("PAYPAL"))
blocks.
7. Observer Pattern — Spring Events
Order created:
publishEvent(
new OrderCreatedEvent()
);
Listeners:
@EventListener
void sendEmail()
@EventListener
void updateAnalytics()
@EventListener
void generateInvoice()
Flow:
Order Service
↓
Publish Event
↓
Spring Event Bus
↓
Email Listener
Analytics Listener
Invoice Listener
Publisher knows nothing about listeners.
This is pure Observer Pattern.
8. Adapter Pattern — Spring MVC
Client request:
GET /users
reaches:
DispatcherServlet
But controllers can have different forms:
@Controller
@RestController
HttpRequestHandler
Different interfaces.
Spring introduces:
HandlerAdapter
Flow:
DispatcherServlet
↓
HandlerAdapter
↓
Actual Controller
Adapter converts various controller styles into one common execution model.
Interview-Winning Answer
If asked:
Explain how Spring uses design patterns internally.
You can say:
Spring’s core container is based on Factory and Singleton patterns. BeanFactory/ApplicationContext create and manage singleton beans. Dependency Injection removes tight coupling by letting the container assemble object graphs. Spring AOP, @Transactional, @Cacheable, and Security use dynamic Proxy patterns to add behavior around business methods. JdbcTemplate and RestTemplate implement the Template Method pattern by handling common workflow steps while allowing customization. Spring Events use the Observer pattern, multiple bean implementations leverage the Strategy pattern, and Spring MVC uses Adapter pattern through HandlerAdapter to support different controller types.
That answer demonstrates both design pattern knowledge and Spring internals, which is what most Java/Spring interviewers are looking for.