Design Patterns in MyBatis: Builder, Factory, Singleton, Proxy, Composite, Template Method, Adapter, Decorator, and Iterator
This article analyses how MyBatis applies nine classic design patterns—Builder, Factory, Singleton, Proxy, Composite, Template Method, Adapter, Decorator, and Iterator—by examining its source code, illustrating each pattern with explanations and concrete Java examples to deepen understanding of software design in backend development.
Although most developers only know the 26 classic design patterns at a conceptual level, they rarely encounter them in real projects. MyBatis, a popular Java persistence framework, heavily uses many of these patterns. Reading its source code and observing the patterns in action helps developers gain a deeper grasp of design patterns.
MyBatis employs at least the following patterns:
Builder – e.g., SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder, CacheBuilder Factory – e.g., SqlSessionFactory, ObjectFactory, MapperProxyFactory Singleton – e.g., ErrorContext, LogFactory Proxy – core of MyBatis, such as MapperProxy, ConnectionLogger; uses JDK dynamic proxies and cglib/javassist for lazy loading.
Composite – e.g., SqlNode hierarchy and its subclasses like ChooseSqlNode Template Method – e.g., BaseExecutor defines the skeleton of SQL execution, delegating specific steps to subclasses.
Adapter – the Log interface adapts various logging frameworks (log4j, slf4j, etc.).
Decorator – cache implementation uses a chain of decorators (e.g., FifoCache, LruCache, LoggingCache).
Iterator – PropertyTokenizer implements Iterator to traverse property strings.
1. Builder Pattern
The Builder pattern separates the construction of a complex object from its representation. In MyBatis, SqlSessionFactoryBuilder reads configuration files, builds a Configuration object, and then creates a SqlSessionFactory. The process involves several builders such as XMLConfigBuilder, XMLMapperBuilder, and XMLStatementBuilder, each handling file parsing, Xpath processing, reflection, and caching.
Typical builder methods start with build*. For example, SqlSessionFactoryBuilder contains:
public SqlSessionFactory build(InputStream inputStream) { ... }2. Factory Pattern
MyBatis uses a simple factory for SqlSessionFactory. The factory method creates different SqlSession instances based on parameters such as auto‑commit, executor type, or transaction isolation level.
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { ... }The method obtains the environment, creates a TransactionFactory, builds a Transaction, then a Executor, and finally returns a DefaultSqlSession.
3. Singleton Pattern
Singleton ensures a class has only one instance. MyBatis uses it for ErrorContext (thread‑local singleton) and LogFactory (global singleton). Example of ErrorContext:
public static ErrorContext instance() {
ErrorContext context = LOCAL.get();
if (context == null) {
context = new ErrorContext();
LOCAL.set(context);
}
return context;
}4. Proxy Pattern
MyBatis relies on proxies so developers only need to write mapper interfaces. MapperProxyFactory creates a JDK dynamic proxy that implements the mapper interface and forwards method calls to MapperMethod which executes the actual SQL.
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}5. Composite Pattern
The SqlNode interface and its implementations form a tree structure that represents dynamic SQL. Each node implements boolean apply(DynamicContext context). Leaf nodes (e.g., TextSqlNode) directly append SQL, while composite nodes (e.g., IfSqlNode) evaluate conditions and recursively apply child nodes.
6. Template Method Pattern
BaseExecutordefines the skeleton of SQL execution (query, update, batch) and leaves the concrete steps to subclasses such as SimpleExecutor, ReuseExecutor, and BatchExecutor. Abstract methods include doUpdate, doFlushStatements, and doQuery.
protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;7. Adapter Pattern
The Log interface abstracts logging. MyBatis provides implementations for various logging frameworks (log4j, slf4j, commons‑logging). Each implementation adapts the external logger to the Log contract.
public class Log4jImpl implements Log {
private Logger log;
public Log4jImpl(String clazz) { log = Logger.getLogger(clazz); }
@Override public void debug(String s) { log.log(FQCN, Level.DEBUG, s, null); }
// other methods ...
}8. Decorator Pattern
MyBatis cache uses a chain of decorators around a core PerpetualCache. Decorators such as FifoCache, LruCache, LoggingCache, SerializedCache, and SynchronizedCache add eviction policies, logging, serialization, and thread safety.
9. Iterator Pattern
PropertyTokenizerimplements Iterator<PropertyTokenizer> to split a property expression like user.address[0].city into tokens. It provides hasNext() and next() methods for sequential traversal.
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
private String name; private String indexedName; private String index; private String children;
public PropertyTokenizer(String fullname) { ... }
@Override public boolean hasNext() { return children != null; }
@Override public PropertyTokenizer next() { return new PropertyTokenizer(children); }
// getters ...
}The article concludes with references to design‑pattern books and MyBatis deep‑dive articles.
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.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.
