Summary of Design Patterns Used in the Spring Framework
This article explains how the Spring framework implements various classic design patterns—including Simple Factory, Factory Method, Singleton, Adapter, Decorator, Proxy, Observer, Strategy, and Template Method—detailing their implementation mechanisms, underlying principles, and practical significance within Spring's bean lifecycle and extension points.
1. Simple Factory (not one of the 23 GoF patterns)
In Spring, BeanFactory embodies the simple factory pattern: it returns a bean instance based on a unique identifier, with creation timing determined by the specific configuration.
Implementation
The bean container reads XML bean definitions, converts each <bean> element into a BeanDefinition , and registers them in a ConcurrentHashMap via BeanDefinitionRegistry . Developers can insert custom code by implementing BeanFactoryPostProcessor , e.g., PropertyPlaceholderConfigurer for placeholder resolution.
Bean Instantiation Phase
During instantiation, Spring uses reflection or CGLIB and offers several extension points:
Aware interfaces (e.g., BeanFactoryAware ) inject corresponding infrastructure objects.
BeanPostProcessor allows custom logic before and after bean initialization.
InitializingBean provides a callback after property population.
DisposableBean handles cleanup before bean destruction.
Design Significance
Enables loose coupling by delegating object creation to the container and allows additional processing through Spring’s lifecycle interfaces.
2. Factory Method
Implementation
Implemented via the FactoryBean interface. When a bean implements FactoryBean , Spring calls its getObject() method and returns the produced object rather than the factory itself.
Example
Typical usage is the integration of Spring with MyBatis, where SqlSessionFactoryBean implements FactoryBean and the actual SqlSessionFactory is obtained from getObject() .
Code Example:
public Object getSingleton(String beanName){
// allow early reference
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);
}3. Singleton Pattern
Spring’s default bean scope is singleton. The AbstractBeanFactory#getBean method eventually calls getSingleton , which implements a double‑checked locking mechanism to ensure a single instance per bean name.
Summary: Guarantees one instance per bean and provides a global access point via the BeanFactory .
4. Adapter Pattern
Implemented in Spring MVC by HandlerAdapter , which adapts various handler types to a common execution contract. The DispatcherServlet obtains a handler from HandlerMapping , delegates to the appropriate HandlerAdapter , and finally returns a ModelAndView .
5. Decorator Pattern
Spring uses wrapper classes whose names contain Wrapper or Decorator . These classes dynamically add responsibilities to existing objects without subclassing, providing more flexible feature extension.
6. Proxy Pattern
AOP in Spring is built on dynamic proxying. At runtime, Spring creates a proxy for the target object, weaving aspects into the proxy. Both dynamic (JDK or CGLIB) and static proxies are supported.
7. Observer Pattern
Spring’s event‑driven model follows the observer pattern. Core components include:
ApplicationEvent (the event object).
ApplicationListener<E extends ApplicationEvent> (the observer).
ApplicationEventPublisher (the subject).
When an event is published, all registered listeners receive it.
public abstract class ApplicationEvent extends EventObject {
private final long timestamp = System.currentTimeMillis();
public ApplicationEvent(Object source) { super(source); }
public final long getTimestamp() { return this.timestamp; }
} public interface ApplicationListener
extends EventListener {
void onApplicationEvent(E event);
} public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}8. Strategy (Resource) Pattern
Spring’s Resource interface abstracts various underlying resources (URL, classpath, file system, servlet context, input stream, byte array). Specific implementations such as UrlResource , ClassPathResource , and FileSystemResource provide the concrete access logic.
9. Template Method Pattern
Spring combines the template method with callbacks. The abstract template defines the algorithm skeleton, while concrete callbacks (e.g., StatementCallback for JDBC) supply the variable part.
public abstract class JdbcTemplate {
public final Object execute(String sql) {
Connection con = null; Statement stmt = null;
try {
con = getConnection();
stmt = con.createStatement();
Object ret = executeWithStatement(stmt, sql);
return ret;
} finally {
closeStatement(stmt);
releaseConnection(con);
}
}
protected abstract Object executeWithStatement(Statement stmt, String sql);
} public interface StatementCallback {
Object doWithStatement(Statement stmt);
} public final Object execute(StatementCallback callback) {
Connection con = null; Statement stmt = null;
try {
con = getConnection();
stmt = con.createStatement();
return callback.doWithStatement(stmt);
} finally {
closeStatement(stmt);
releaseConnection(con);
}
}By passing a callback, developers inject custom logic without subclassing the template class.
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.
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.