2026/5/24 2:15:05
网站建设
项目流程
信息产业部互联网网站管理工作细则,wordpress电商模板下载,wordpress后台功能添加,从化网站开发MyBatis设计模式深度解析#xff08;二#xff09;一、MyBatis整体架构与设计模式续篇在上一篇文章中#xff0c;我们深入讲解了MyBatis中的构建者模式、工厂模式和代理模式。本文将继续探讨MyBatis中另外三种重要的设计模式#xff1a;装饰器模式、模板方法模式和策略模式…MyBatis设计模式深度解析二一、MyBatis整体架构与设计模式续篇在上一篇文章中我们深入讲解了MyBatis中的构建者模式、工厂模式和代理模式。本文将继续探讨MyBatis中另外三种重要的设计模式装饰器模式、模板方法模式和策略模式。这些设计模式的应用使得MyBatis在功能扩展、性能优化和架构灵活性方面表现出色。1.1 MyBatis整体架构回顾MyBatis采用分层架构设计从上到下包括应用层用户应用程序接口层SqlSession、Mapper接口核心处理层SQL解析、执行、结果映射基础支撑层缓存、事务、类型处理、日志等数据层数据源、连接池、JDBC驱动在本文中我们将重点探讨装饰器模式、模板方法模式和策略模式在这些层次中的应用。1.2 本文涉及的设计模式装饰器模式Decorator PatternCachingExecutor、Cache装饰器链模板方法模式Template Method PatternBaseExecutor、BaseTypeHandler策略模式Strategy PatternRoutingStatementHandler、不同Executor策略二、装饰器模式Decorator Pattern装饰器模式是一种结构型设计模式它允许你在不改变对象结构的情况下动态地为对象添加新的行为。装饰器模式通过将对象包装在装饰器类中来实现功能的增强。2.1 CachingExecutorCachingExecutor是MyBatis中最典型的装饰器模式应用。它为Executor添加了二级缓存功能。2.1.1 类定义public class CachingExecutor implements Executor { private final Executor delegate; // 被装饰的Executor private final TransactionalCacheManager tcm new TransactionalCacheManager(); public CachingExecutor(Executor delegate) { this.delegate delegate; // 确保被装饰的Executor类型是SIMPLE、REUSE或BATCH if (delegate instanceof CachingExecutor) { throw new IllegalArgumentException(Cannot wrap a CachingExecutor); } } Override public E ListE query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { // 1. 获取绑定SQL BoundSql boundSql ms.getBoundSql(parameterObject); // 2. 创建缓存Key CacheKey key createCacheKey(ms, parameterObject, rowBounds, boundSql); // 3. 执行查询先查缓存缓存没有则查数据库 return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } Override public E ListE query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { // 4. 获取MappedStatement的缓存配置 Cache cache ms.getCache(); if (cache ! null) { // 5. 刷新缓存如果需要 flushCacheIfRequired(ms); if (ms.isUseCache() resultHandler null) { // 6. 确保参数不为null时才使用缓存 ensureNoOutParams(ms, boundSql); // 7. 从事务缓存管理器获取缓存 SuppressWarnings(unchecked) ListE list (ListE) tcm.getObject(cache, key); if (list null) { // 8. 缓存未命中委托给被装饰的Executor执行查询 list delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); // 9. 将查询结果放入缓存 tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } } // 10. 没有配置缓存直接委托给被装饰的Executor return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } Override public int update(MappedStatement ms, Object parameterObject) throws SQLException { // 更新操作先刷新缓存 flushCacheIfRequired(ms); // 委托给被装饰的Executor执行更新 return delegate.update(ms, parameterObject); } private void flushCacheIfRequired(MappedStatement ms) { Cache cache ms.getCache(); if (cache ! null ms.isFlushCacheRequired()) { tcm.clear(cache); } } }2.1.2 装饰器模式的优势不修改原始类通过包装而非继承来扩展功能动态组合可以在运行时动态地添加或删除功能职责单一每个装饰器只负责一个功能灵活扩展可以多层嵌套实现功能的灵活组合2.2 Cache装饰器链MyBatis的缓存系统也大量使用了装饰器模式。Cache接口有多个装饰器实现形成了一个装饰器链。2.2.1 Cache接口public interface Cache { String getId(); void putObject(Object key, Object value); Object getObject(Object key); Object removeObject(Object key); void clear(); int getSize(); ReadWriteLock getReadWriteLock(); }2.2.2 Cache装饰器实现// 1. PerpetualCache - 基础缓存实现 public class PerpetualCache implements Cache { private final String id; private MapObject, Object cache new HashMap(); public PerpetualCache(String id) { this.id id; } Override public void putObject(Object key, Object value) { cache.put(key, value); } Override public Object getObject(Object key) { return cache.get(key); } Override public Object removeObject(Object key) { return cache.remove(key); } Override public void clear() { cache.clear(); } } // 2. LruCache - LRU淘汰策略装饰器 public class LruCache implements Cache { private final Cache delegate; private MapObject, Object keyMap; private Object eldestKey; public LruCache(Cache delegate) { this.delegate delegate; setSize(1024); } Override public void putObject(Object key, Object value) { delegate.putObject(key, value); cycleKeyList(key); } Override public Object getObject(Object key) { keyMap.get(key); // 触发LRU return delegate.getObject(key); } private void cycleKeyList(Object key) { keyMap.put(key, key); if (eldestKey ! null) { delegate.removeObject(eldestKey); eldestKey null; } } } // 3. FifoCache - FIFO淘汰策略装饰器 public class FifoCache implements Cache { private final Cache delegate; private final DequeObject keyList; private int size; public FifoCache(Cache delegate) { this.delegate delegate; this.keyList new LinkedList(); this.size 1024; } Override public void putObject(Object key, Object value) { cycleKeyList(key); delegate.putObject(key, value); } private void cycleKeyList(Object key) { keyList.addLast(key); if (keyList.size() size) { Object oldestKey keyList.removeFirst(); delegate.removeObject(oldestKey); } } } // 4. SoftCache/WeakCache - 软引用/弱引用装饰器 public class SoftCache implements Cache { private final Cache delegate; private final MapObject, Object hardLinksToAvoidGarbageCollection; Override public void putObject(Object key, Object value) { delegate.putObject(key, new SoftEntry(value)); } Override public Object getObject(Object key) { Object value delegate.getObject(key); if (value instanceof SoftEntry) { return ((SoftEntry) value).get(); } return value; } } // 5. BlockingCache - 阻塞装饰器防止缓存击穿 public class BlockingCache implements Cache { private final Cache delegate; private final ConcurrentHashMapObject, CountDownLatch locks; Override public void putObject(Object key, Object value) { try { delegate.putObject(key, value); } finally { releaseLock(key); } } Override public Object getObject(Object key) { acquireLock(key); Object value delegate.getObject(key); if (value ! null) { releaseLock(key); } return value; } private void acquireLock(Object key) { CountDownLatch latch new CountDownLatch(1); CountDownLatch existing locks.putIfAbsent(key, latch); if (existing ! null) { try { existing.await(); } catch (InterruptedException e) { Thread.interrupted(); } } } } // 6. LoggingCache - 日志装饰器 public class LoggingCache implements Cache { private final Cache delegate; private int hits 0; private int requests 0; Override public void putObject(Object key, Object value) { delegate.putObject(key, value); } Override public Object getObject(Object key) { requests; final Object value delegate.getObject(key); if (value ! null) { hits; } if (log.isDebugEnabled()) { log.debug(Cache Hit Ratio [ getId() ]: getHitRatio()); } return value; } private double getHitRatio() { return (double) hits / (double) requests; } } // 7. ScheduledCache - 定时清理装饰器 public class ScheduledCache implements Cache { private final Cache delegate; private long clearInterval; private long lastClear; Override public void putObject(Object key, Object value) { clearWhenStale(); delegate.putObject(key, value); } Override public Object getObject(Object key) { return clearWhenStale() ? null : delegate.getObject(key); } private boolean clearWhenStale() { if (System.currentTimeMillis() - lastClear clearInterval) { clear(); return true; } return false; } } // 8. SerializedCache - 序列化装饰器 public class SerializedCache implements Cache { private final Cache delegate; Override public void putObject(Object key, Object value) { if (value ! null !(value instanceof Serializable)) { throw new CacheException(Cacheed object is not serializable: value); } delegate.putObject(key, serialize(value)); } Override public Object getObject(Object key) { Object object delegate.getObject(key); return object null ? null : deserialize((byte[]) object); } } // 9. SynchronizedCache - 同步装饰器 public class SynchronizedCache implements Cache { private final Cache delegate; Override public synchronized void putObject(Object key, Object value) { delegate.putObject(key, value); } Override public synchronized Object getObject(Object key) { return delegate.getObject(key); } Override public synchronized void clear() { delegate.clear(); } } // 10. TransactionalCache - 事务缓存装饰器 public class TransactionalCache implements Cache { private final Cache delegate; private boolean clearOnCommit; private MapObject, Object entriesToAddOnCommit; Override public void putObject(Object key, Object value) { entriesToAddOnCommit.put(key, value); } Override public Object getObject(Object key) { if (clearOnCommit) { return null; } return delegate.getObject(key); } public void commit() { if (clearOnCommit) { delegate.clear(); } for (Map.EntryObject, Object entry : entriesToAddOnCommit.entrySet()) { delegate.putObject(entry.getKey(), entry.getValue()); } reset(); } }2.2.3 Cache装饰器链的构建public class CacheBuilder { private String id; private Class? extends Cache implementation; private ListClass? extends Cache decorators; public Cache build() { setDefaultImplementations(); Cache cache newBaseCacheInstance(implementation, id); setCacheProperties(cache); // 应用装饰器 for (Class? extends Cache decorator : decorators) { cache newCacheDecoratorInstance(decorator, cache); setCacheProperties(cache); } return cache; } }2.3 装饰器模式的应用场景在MyBatis中装饰器模式主要应用于Executor增强CachingExecutor为Executor添加二级缓存功能Cache功能扩展通过各种Cache装饰器添加LRU、FIFO、日志等功能StatementHandler增强通过RoutingStatementHandler路由到不同的实现2.4 装饰器模式 vs 继承装饰器模式相比继承的优势对比项装饰器模式继承扩展方式动态组合静态继承灵活性高低代码复用好一般类数量可能增加可能爆炸复杂度中等简单三、模板方法模式Template Method Pattern模板方法模式是一种行为型设计模式它在父类中定义了一个算法的框架允许子类在不改变算法结构的情况下重写算法的特定步骤。3.1 BaseExecutorBaseExecutor是MyBatis中模板方法模式的典型应用它定义了SQL执行的基本流程将具体的执行逻辑留给子类实现。3.1.1 BaseExecutor核心代码public abstract class BaseExecutor implements Executor { protected Transaction transaction; protected Executor wrapper; Override public E ListE query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { // 1. 获取绑定SQL BoundSql boundSql ms.getBoundSql(parameter); // 2. 创建缓存Key CacheKey key createCacheKey(ms, parameter, rowBounds, boundSql); // 3. 调用模板方法 return query(ms, parameter, rowBounds, resultHandler, key, boundSql); } // 模板方法 - 定义算法骨架 Override public E ListE query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity(executing a query).object(ms.getId()); if (closed) { throw new ExecutorException(Executor was closed.); } if (queryStack 0 ms.isFlushCacheRequired()) { clearLocalCache(); } ListE list; try { queryStack; // 4. 检查一级缓存 list resultHandler null ? (ListE) localCache.getObject(key) : null; if (list ! null) { handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { // 5. 缓存未命中调用抽象方法查询数据库 list queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { queryStack--; } if (queryStack 0) { deferLoadIfNeeded(); } return list; } // 从数据库查询 - 也是模板方法 private E ListE queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ListE list; localCache.putObject(key, EXECUTION_PLACEHOLDER); try { // 6. 调用抽象方法由子类实现具体查询逻辑 list doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { localCache.removeObject(key); } localCache.putObject(key, list); return list; } // 抽象方法 - 由子类实现具体的查询逻辑 protected abstract E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException; // 抽象方法 - 由子类实现具体的更新逻辑 protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException; // 其他抽象方法... }3.1.2 BaseExecutor的子类实现// 1. SimpleExecutor - 简单执行器 public class SimpleExecutor extends BaseExecutor { Override protected E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt null; try { // 1. 创建Statement stmt createStatement(ms, parameter, rowBounds); // 2. 设置参数 setStatementParameters(ms, stmt, parameter, rowBounds, boundSql); // 3. 执行查询 return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } } Override protected int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt null; try { Configuration configuration ms.getConfiguration(); StatementHandler handler configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); stmt prepareStatement(handler, ms.getStatementLog()); return handler.update(stmt); } finally { closeStatement(stmt); } } } // 2. ReuseExecutor - 重用执行器 public class ReuseExecutor extends BaseExecutor { private final MapString, Statement statementMap new HashMap(); Override protected E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Configuration configuration ms.getConfiguration(); StatementHandler handler configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql); Statement stmt prepareStatement(handler, ms.getStatementLog(), true); return handler.query(stmt, resultHandler); } private Statement prepareStatement(StatementHandler handler, Log statementLog, boolean isReusable) throws SQLException { BoundSql boundSql handler.getBoundSql(); String sql boundSql.getSql(); Statement stmt; if (isReusable) { // 尝试重用Statement stmt statementMap.get(sql); if (stmt null) { stmt handler.prepare(statementLog.getConnection(), transaction.getTimeout()); statementMap.put(sql, stmt); } } else { stmt handler.prepare(statementLog.getConnection(), transaction.getTimeout()); } handler.parameterize(stmt); return stmt; } } // 3. BatchExecutor - 批量执行器 public class BatchExecutor extends BaseExecutor { private final ListStatement statementList new ArrayList(); private final ListBatchResult batchResultList new ArrayList(); Override protected int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Configuration configuration ms.getConfiguration(); StatementHandler handler configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); Statement stmt prepareStatement(handler, ms.getStatementLog()); handler.parameterize(stmt); batchResultList.add(new BatchResult(ms.getStatement(), ms.getId(), parameter)); handler.batch(stmt); return BATCH_UPDATE_RETURN_VALUE; } Override public ListBatchResult doFlushStatements(boolean isRollback) { ListBatchResult results new ArrayList(); try { for (int i 0, n statementList.size(); i n; i) { Statement stmt statementList.get(i); BatchResult batchResult batchResultList.get(i); try { int[] updateCounts stmt.executeBatch(); batchResult.setUpdateCounts(updateCounts); results.add(batchResult); } catch (BatchUpdateException e) { StringBuilder message new StringBuilder(); message.append(batchResult.getStatement()).append( failed.); if (updateCounts ! null updateCounts.length 0) { message.append( Update counts: ); for (int j 0; j updateCounts.length; j) { message.append(updateCounts[j]).append(;); } } throw new BatchExecutorException(message.toString(), e, updateCounts, batchResult.getStatement()); } } return results; } finally { clearLocalCache(); statementList.clear(); batchResultList.clear(); } } }3.2 BaseTypeHandlerBaseTypeHandler也是模板方法模式的应用它定义了类型处理的基本流程。3.2.1 BaseTypeHandler核心代码public abstract class BaseTypeHandlerT extends TypeReferenceT implements TypeHandlerT { Override public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { // 模板方法设置非空参数 setParameter(ps, i, parameter, jdbcType); } Override public T getNullableResult(ResultSet rs, String columnName) throws SQLException { // 模板方法通过列名获取结果 T result getNullableResult(rs, columnName); return rs.wasNull() ? null : result; } Override public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException { // 模板方法通过列索引获取结果 T result getNullableResult(rs, columnIndex); return rs.wasNull() ? null : result; } Override public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { // 模板方法从存储过程获取结果 T result getNullableResult(cs, columnIndex); return cs.wasNull() ? null : result; } // 抽象方法由子类实现具体的参数设置逻辑 public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; // 抽象方法由子类实现具体的结果获取逻辑 public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException; public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException; public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException; }3.2.2 具体的TypeHandler实现// StringTypeHandler public class StringTypeHandler extends BaseTypeHandlerString { Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } } // IntegerTypeHandler public class IntegerTypeHandler extends BaseTypeHandlerInteger { Override public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType) throws SQLException { ps.setInt(i, parameter); } Override public Integer getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getInt(columnName); } Override public Integer getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getInt(columnIndex); } Override public Integer getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getInt(columnIndex); } }3.3 模板方法模式的优势代码复用将公共逻辑提取到父类避免重复代码扩展性强子类可以灵活实现特定步骤算法稳定算法框架固定保证一致性易于维护修改算法只需修改父类四、策略模式Strategy Pattern策略模式是一种行为型设计模式它定义了一系列算法并将每个算法封装起来使它们可以相互替换。策略模式让算法独立于使用它的客户端。4.1 RoutingStatementHandlerRoutingStatementHandler是MyBatis中策略模式的典型应用它根据MappedStatement的配置路由到不同的StatementHandler实现。4.1.1 RoutingStatementHandler源码public class RoutingStatementHandler implements StatementHandler { private final StatementHandler delegate; public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { // 根据Statement类型选择策略 switch (ms.getStatementType()) { case STATEMENT: delegate new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case PREPARED: delegate new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case CALLABLE: delegate new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; default: throw new ExecutorException(Unknown statement type: ms.getStatementType()); } } Override public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { return delegate.prepare(connection, transactionTimeout); } Override public void parameterize(Statement statement) throws SQLException { delegate.parameterize(statement); } Override public E ListE query(Statement statement, ResultHandler resultHandler) throws SQLException { return delegate.query(statement, resultHandler); } Override public int update(Statement statement) throws SQLException { return delegate.update(statement); } // 其他方法都委托给delegate... }4.1.2 三种StatementHandler策略// 1. SimpleStatementHandler - 简单SQL策略 public class SimpleStatementHandler extends BaseStatementHandler { Override protected Statement instantiateStatement(Connection connection) throws SQLException { if (mappedStatement.getResultSetType() ResultSetType.FORWARD_ONLY) { return connection.createStatement(); } else { return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } } Override public int update(Statement statement) throws SQLException { String sql boundSql.getSql(); Object parameterObject boundSql.getParameterObject(); KeyGenerator keyGenerator mappedStatement.getKeyGenerator(); int rows; if (keyGenerator instanceof Jdbc3KeyGenerator) { statement.execute(sql, Statement.RETURN_GENERATED_KEYS); rows statement.getUpdateCount(); keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject); } else if (keyGenerator instanceof SelectKeyGenerator) { statement.execute(sql); rows statement.getUpdateCount(); keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject); } else { statement.execute(sql); rows statement.getUpdateCount(); } return rows; } } // 2. PreparedStatementHandler - 预编译SQL策略 public class PreparedStatementHandler extends BaseStatementHandler { Override protected Statement instantiateStatement(Connection connection) throws SQLException { String sql boundSql.getSql(); if (mappedStatement.getResultSetType() ResultSetType.FORWARD_ONLY) { return connection.prepareStatement(sql); } else { return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } } Override public void parameterize(Statement statement) throws SQLException { parameterHandler.setParameters((PreparedStatement) statement); } Override public int update(Statement statement) throws SQLException { PreparedStatement ps (PreparedStatement) statement; ps.execute(); int rows ps.getUpdateCount(); Object parameterObject boundSql.getParameterObject(); KeyGenerator keyGenerator mappedStatement.getKeyGenerator(); keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject); return rows; } } // 3. CallableStatementHandler - 存储过程策略 public class CallableStatementHandler extends BaseStatementHandler { Override protected Statement instantiateStatement(Connection connection) throws SQLException { String sql boundSql.getSql(); if (mappedStatement.getResultSetType() ResultSetType.FORWARD_ONLY) { return connection.prepareCall(sql); } else { return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } } Override public void parameterize(Statement statement) throws SQLException { registerOutputParameters((CallableStatement) statement); parameterHandler.setParameters((CallableStatement) statement); } Override public int update(Statement statement) throws SQLException { CallableStatement cs (CallableStatement) statement; cs.execute(); int rows cs.getUpdateCount(); Object parameterObject boundSql.getParameterObject(); KeyGenerator keyGenerator mappedStatement.getKeyGenerator(); keyGenerator.processAfter(executor, mappedStatement, cs, parameterObject); return rows; } } public class Configuration { public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType executorType null ? defaultExecutorType : executorType; Executor executor; // 根据ExecutorType选择策略 if (ExecutorType.BATCH executorType) { executor new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE executorType) { executor new ReuseExecutor(this, transaction); } else { executor new SimpleExecutor(this, transaction); } // 如果启用缓存装饰为CachingExecutor if (cacheEnabled) { executor new CachingExecutor(executor); } return (Executor) interceptorChain.pluginAll(executor); } }4.2.2 三种Executor策略对比Executor类型特点适用场景性能SimpleExecutor每次执行创建新Statement一般查询、单条操作中等ReuseExecutor重用Statement执行相同SQL多次较好BatchExecutor批量执行SQL批量插入、更新最好4.3 策略模式的优势算法可替换可以灵活切换不同的算法实现代码解耦算法的实现与使用分离扩展方便新增策略只需实现新类简化测试可以独立测试每个策略4.4 策略模式 vs 模板方法模式对比项策略模式模板方法模式算法结构可变固定实现方式组合继承灵活性高中等复杂度较高较低五、设计模式的综合应用在MyBatis中多种设计模式往往协同工作共同完成复杂的功能。5.1 Executor的创建过程// 1. 模板方法模式BaseExecutor定义执行流程 // 2. 策略模式根据ExecutorType选择SimpleExecutor、ReuseExecutor或BatchExecutor // 3. 装饰器模式CachingExecutor为Executor添加缓存功能 // 4. 代理模式Plugin为Executor添加拦截功能 Executor executor configuration.newExecutor(transaction, ExecutorType.SIMPLE);5.2 Cache的构建过程// 1. 装饰器模式多层Cache装饰器嵌套 // 2. 模板方法模式BaseExecutor定义查询流程使用缓存 Cache cache new CacheBuilder(myCache) .implementation(PerpetualCache.class) .addDecorator(LruCache.class) .addDecorator(FifoCache.class) .addDecorator(ScheduledCache.class) .build();5.3 StatementHandler的选择过程// 1. 策略模式RoutingStatementHandler路由到不同的StatementHandler // 2. 模板方法模式BaseStatementHandler定义Statement处理流程 // 3. 代理模式LoggerStatementHandler添加日志功能 StatementHandler handler configuration.newStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);六、最佳实践与建议6.1 装饰器模式应用场景当满足以下条件时可以考虑使用装饰器模式需要动态地、透明地给对象添加功能不希望通过继承来扩展功能避免类爆炸需要组合多个功能应用示例// 为服务添加缓存、日志、监控功能 Service service new LoggingService( new MonitoringService( new CachingService( new BasicService() ) ) );6.2 模板方法模式应用场景当满足以下条件时可以考虑使用模板方法模式算法的整体结构固定部分步骤可变多个子类有共同的行为逻辑需要控制子类的扩展应用示例public abstract class AbstractDataService { // 模板方法定义数据处理流程 public final void processData(String data) { validate(data); // 验证 data transform(data); // 转换 save(data); // 保存 } protected abstract void validate(String data); protected abstract String transform(String data); protected abstract void save(String data); }6.3 策略模式应用场景当满足以下条件时可以考虑使用策略模式有多种算法可以相互替换算法的使用和实现分离需要在运行时选择算法应用示例// 支付策略 public interface PaymentStrategy { void pay(int amount); } public class CreditCardPayment implements PaymentStrategy { public void pay(int amount) { // 信用卡支付逻辑 } } public class WeChatPayPayment implements PaymentStrategy { public void pay(int amount) { // 微信支付逻辑 } } // 上下文 public class PaymentContext { private PaymentStrategy strategy; public void setPaymentStrategy(PaymentStrategy strategy) { this.strategy strategy; } public void processPayment(int amount) { strategy.pay(amount); } }6.4 设计模式选择指南场景推荐模式理由需要动态添加功能装饰器模式灵活组合避免继承算法结构固定部分可变模板方法模式代码复用结构清晰算法需要相互替换策略模式解耦算法和使用创建复杂对象构建者模式分步构建代码清晰创建对象族工厂模式解耦创建和使用控制对象访问代理模式增强功能不修改原类6.5 避免过度设计虽然设计模式很有用但也要避免过度设计简单问题简单解决不要为了使用模式而使用模式按需设计根据实际需求选择合适的模式保持简洁简单的设计往往比复杂的设计更好重构时再引入先实现功能重构时再应用模式七、总结本文深入讲解了MyBatis中的装饰器模式、模板方法模式和策略模式通过源码分析和示例代码帮助读者理解这些设计模式在实际框架中的应用。7.1 关键要点装饰器模式CachingExecutor为Executor添加二级缓存功能Cache装饰器链提供LRU、FIFO、日志等多种功能动态组合灵活扩展模板方法模式BaseExecutor定义SQL执行的基本流程BaseTypeHandler定义类型处理的基本流程代码复用算法稳定策略模式RoutingStatementHandler根据配置路由到不同的StatementHandler不同Executor策略适用于不同的执行场景算法可替换代码解耦7.2 设计模式的价值提高代码质量使代码更易读、易维护、易扩展促进架构设计提供成熟的设计思想和解决方案增强团队协作统一的设计语言和思维方式提升个人能力深入理解设计模式是成为高级工程师的必经之路