How Spring Implements 9 Core Design Patterns – From Simple Factory to Template Method
This article explains how Spring applies nine classic design patterns—including Simple Factory, Factory Method, Singleton, Adapter, Decorator, Proxy, Observer, Strategy, and Template Method—detailing their implementation approaches, underlying principles, and the benefits they bring to Spring's IoC container and AOP mechanisms.
Spring's design pattern summary covers nine patterns: Simple Factory, Factory Method, Singleton, Adapter, Decorator, Proxy, Observer, Strategy, and Template Method.
1. Simple Factory (not one of the 23 GoF patterns)
Implementation
BeanFactory in Spring is an embodiment of the simple factory pattern: it returns a bean instance based on a unique identifier, with creation timing determined by the specific scenario.
Essence
A factory class decides which product class to instantiate based on the provided parameters.
Principle
Bean container startup phase:
Read bean XML configuration files and convert each bean element into a BeanDefinition object.
Register these BeanDefinition objects into the BeanFactory via BeanDefinitionRegistry, storing them in a ConcurrentHashMap.
After registration, Spring offers an extension point through BeanFactoryPostProcessor allowing custom code insertion, e.g., PropertyPlaceholderConfigurer for placeholder resolution.
Bean instantiation phase:
Beans are instantiated via reflection or CGLIB, during which Spring exposes many extension points:
Aware interfaces (e.g., BeanFactoryAware) – Spring injects the corresponding BeanFactory instance into beans implementing these interfaces.
BeanPostProcessor – Spring invokes its methods during bean instantiation.
InitializingBean – Spring calls its methods after property injection.
DisposableBean – Spring calls its methods when the bean is destroyed.
Design significance
Loose coupling : By delegating dependency resolution to the BeanFactory, hard‑coded dependencies become configurable, achieving loose coupling.
Additional bean processing : Implementing Spring’s extension interfaces allows extra handling during the bean lifecycle; the [Very Important] note emphasizes this.
2. Factory Method
Implementation
Use the FactoryBean interface.
Principle
A bean that implements FactoryBean is a factory bean; when getBean() is called, Spring automatically invokes its getObject() method and returns the result instead of the factory itself.
Example
Typical example: integration of Spring with MyBatis.
Code example:
Explanation:
The bean shown implements FactoryBean, so the returned object is the result of SqlSessionFactoryBean.getObject(), not the SqlSessionFactoryBean instance itself.
3. Singleton Pattern
Spring’s default bean scope is singleton.
Dependency injection (including lazy‑init) occurs in AbstractBeanFactory.getBean. The doGetBean method calls getSingleton to create the bean.
Analysis of getSingleton() method:
public Object getSingleton(String beanName){
// parameter true allows early references
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// check cache for existing instance
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// lock and handle early reference
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// invoke getObject of the factory
singletonObject = singletonFactory.getObject();
// record in cache; earlySingletonObjects and singletonFactories are mutually exclusive
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}Process diagram: Spring uses double‑checked locking for singleton bean creation.
Summary
Singleton definition: Ensure a class has only one instance and provide a global access point.
Spring’s implementation: Spring provides the global access point via BeanFactory, but does not enforce singleton at the constructor level because it manages arbitrary Java objects.
4. Adapter Pattern
Implementation
Spring MVC’s HandlerAdapter.
Principle
HandlerAdapterselects and executes the appropriate handler based on handler rules.
Process
DispatcherServletobtains a handler from HandlerMapping, then forwards the request to the corresponding HandlerAdapter, which invokes the handler and returns a ModelAndView to the servlet.
Significance
Adding a new controller only requires a new handler and its matching adapter, making extension straightforward.
5. Decorator Pattern
Implementation
Spring uses wrapper classes whose names contain Wrapper or Decorator.
Essence
Dynamically adds additional responsibilities to an object.
Compared with subclassing, the decorator offers more flexibility for adding functionality.
6. Proxy Pattern
Implementation
AOP in Spring is built on the dynamic proxy pattern.
Dynamic proxy
Created in memory without manually writing proxy classes.
Static proxy
Requires a hand‑written proxy class that delegates to the target object.
Principle
Aspects are woven at runtime; Spring AOP creates a proxy for the target object and injects the aspect logic.
Weaving
Weaving means applying an aspect to a target object and creating a new proxy.
7. Observer Pattern
Implementation
Spring’s event‑driven model uses the observer pattern; listeners implement the observer role.
Specifics
Three parts are required: event source, event, and event listener.
ApplicationEvent (abstract class) extends java.util.EventObject and carries a timestamp.
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; }
}ApplicationListener interface extends EventListener with a single method onApplicationEvent(E event).
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}ApplicationContext is the global container (the event source) and implements ApplicationEventPublisher.
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}Spring’s AbstractApplicationContext registers listeners and publishes events via an ApplicationEventMulticaster.
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
private ApplicationEventMulticaster applicationEventMulticaster;
protected void registerListeners() {
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
}8. Strategy Pattern
Implementation
Spring’s Resource interface provides a flexible strategy for accessing various underlying resources.
Resource interface overview
The interface defines methods such as getInputStream(), exists(), isOpen(), getDescription(), getFile(), and getURL(). Different implementations handle different resource types.
Implementations include:
UrlResource – accesses network resources.
ClassPathResource – accesses class‑path resources.
FileSystemResource – accesses file‑system resources.
ServletContextResource – accesses resources relative to the servlet context.
InputStreamResource – wraps an InputStream.
ByteArrayResource – wraps a byte array.
9. Template Method Pattern
Classic definition
The abstract superclass defines the algorithm skeleton (order of method calls); subclasses implement specific steps.
Benefits: code reuse and reduced duplication; the superclass handles common steps while subclasses provide custom behavior.
Spring’s usage
Spring combines the template method with callback interfaces. Most extension points (e.g., JDBC, Hibernate integration) follow this pattern.
Example – JdbcTemplate:
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) {
// handle exception
} finally {
closeStatement(stmt);
releaseConnection(con);
}
}
protected abstract Object executeWithStatement(Statement stmt, String sql);
}Because JdbcTemplate is abstract, a callback interface ( StatementCallback) is introduced to supply the variable part:
public interface StatementCallback {
Object doWithStatement(Statement stmt);
}Usage example:
JdbcTemplate jdbcTemplate = ...;
final String sql = ...;
StatementCallback callback = new StatementCallback() {
public Object doWithStatement(Statement stmt) {
return ...; // custom logic
}
};
jdbcTemplate.execute(callback);The callback isolates changing code while allowing reuse of the stable connection handling provided by JdbcTemplate.
Source: http://blog.csdn.net/caoxiaohong1005
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.
ITFLY8 Architecture Home
ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.
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.
