How Spring Implements Classic Design Patterns: Factory, Singleton, and More
This article explains how Spring applies classic design patterns such as Simple Factory, Factory Method, Singleton, Adapter, Decorator, Proxy, Observer, Strategy, and Template Method, illustrating each pattern with implementation details, core code snippets, and their significance for loose coupling and extensibility in backend development.
Simple Factory
Implementation
BeanFactory in Spring is an embodiment of the simple factory pattern. It returns a bean instance based on a unique identifier; creation may occur before or after the identifier is supplied depending on the situation.
Essence
A factory class decides which product class to create based on supplied parameters.
Implementation Details
Bean container startup phase:
Read bean XML configuration files and convert each bean element into a BeanDefinition object.
Register these BeanDefinitions with BeanFactory via BeanDefinitionRegistry, storing them in a ConcurrentHashMap.
After registration, Spring provides an extension point allowing custom code via BeanFactoryPostProcessor (e.g., PropertyPlaceholderConfigurer).
Bean instantiation phase:
Instantiation uses reflection or CGLIB. Spring exposes several extension points:
Aware interfaces (e.g., BeanFactoryAware) for injecting the BeanFactory instance.
BeanPostProcessor interface for invoking custom methods during bean creation.
InitializingBean interface for post‑initialization callbacks.
DisposableBean interface for cleanup when a bean is destroyed.
Design Significance
Loose coupling: Dependencies are injected through Spring’s BeanFactory, introducing a third party that resolves bean relationships.
Additional bean processing: By implementing Spring’s extension interfaces, developers can add custom behavior during the bean lifecycle.
Factory Method
Implementation
FactoryBean interface.
Implementation Details
Beans that implement FactoryBean are “factory beans”. When getBean() retrieves such a bean, Spring automatically calls its getObject() method, returning the object produced by getObject() rather than the factory bean itself.
Example
Typical example: integration of Spring with MyBatis.
Code example:
Explanation: Because the bean implements FactoryBean, the returned object is the result of SqlSessionFactoryBean.getObject(), not the SqlSessionFactoryBean instance itself.
Singleton Pattern
Spring’s default bean scope is singleton.
Dependency injection (including lazy‑init) occurs in AbstractBeanFactory.getBean, where doGetBean calls getSingleton to create the bean.
Key method analysis:
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);
}Process diagram: (illustrative image omitted)
Summary:
Singleton ensures a class has only one instance and provides a global access point.
Spring implements the second part by offering a global BeanFactory access point without enforcing constructor‑level singleton control.
Adapter Pattern
Implementation
Spring MVC’s HandlerAdapter.
Implementation Details
HandlerAdapter selects and executes the appropriate Handler based on defined rules.
Process
DispatcherServlet obtains a handler from HandlerMapping, then forwards the request to HandlerAdapter, which invokes the handler. After execution, the handler returns a ModelAndView to the adapter, which passes it back to DispatcherServlet.
Significance
HandlerAdapter simplifies extending handlers: adding a new handler only requires a corresponding adapter.
Decorator Pattern
Implementation
Spring uses wrapper classes (named *Wrapper* or *Decorator*) to add responsibilities dynamically.
Essence
Dynamically adds extra responsibilities to an object, offering more flexibility than subclassing.
Proxy Pattern
Implementation
AOP in Spring is built on dynamic proxy pattern.
Dynamic proxy: created at runtime without manual proxy class.
Static proxy: manually written proxy class that delegates to the target.
Implementation Details
Aspects are woven at runtime; the AOP container creates a proxy object for the target, and Spring AOP weaves the aspect into this proxy.
Weaving means applying an aspect to a target object and creating a new proxy.
Observer Pattern
Implementation
Spring’s event‑driven model uses the observer pattern; listeners implement ApplicationListener.
Components
Three parts: event source, event, and event listener.
(1) ApplicationEvent abstract class – extends java.util.EventObject; events inherit from it.
(2) ApplicationListener interface – extends java.util.EventListener; defines onApplicationEvent(E event).
(3) ApplicationContext interface – the global container that publishes events.
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
} public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
} public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}Strategy Pattern
Implementation
Spring’s Resource interface abstracts various resource‑access strategies.
Resource Interface Overview
Key methods include getInputStream(), exists(), isOpen(), getDescription(), getFile(), getURL(). Different implementations (UrlResource, ClassPathResource, FileSystemResource, ServletContextResource, InputStreamResource, ByteArrayResource) handle specific resource types.
Template Method Pattern
Classic Definition
Superclass defines the skeleton; subclasses implement specific steps.
Spring’s Use
Spring combines template method with callback interfaces (e.g., JdbcTemplate).
Example
public abstract class JdbcTemplate {
public final Object execute(String sql) {
Connection con = null;
Statement stmt = null;
try {
con = getConnection();
stmt = con.createStatement();
Object retValue = executeWithStatement(stmt, sql);
return retValue;
} catch (SQLException e) {
// ...
} finally {
closeStatement(stmt);
releaseConnection(con);
}
}
protected abstract Object executeWithStatement(Statement stmt, String sql);
}Callback interface:
public interface StatementCallback {
Object doWithStatement(Statement stmt);
}JdbcTemplate can execute a callback:
JdbcTemplate jdbcTemplate = ...;
final String sql = ...;
StatementCallback callback = new StatementCallback() {
public Object doWithStatement(Statement stmt) {
return ...;
}
};
jdbcTemplate.execute(callback);Using callbacks avoids subclassing for each variation.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
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.
