wordpress必须关注公众号,安阳seo关键词优化,seo推广怎么做,个人网站备案名文章目录 一、类型#xff1a;创建型模式1.1 工厂模式1.2 单例模式1.3 建造者模式 二、类型#xff1a;结构型模式2.1 适配器模式2.2 代理模式2.3 组合模式2.4 装饰器模式 三、类型#xff1a;行为型模式3.1 模板模式3.2 策略模式3.3 迭代器模式 一、类型#xff1a;创建型… 文章目录 一、类型创建型模式1.1 工厂模式1.2 单例模式1.3 建造者模式 二、类型结构型模式2.1 适配器模式2.2 代理模式2.3 组合模式2.4 装饰器模式 三、类型行为型模式3.1 模板模式3.2 策略模式3.3 迭代器模式 一、类型创建型模式
1.1 工厂模式 SqlSessionFactory.java package com.lino.mybatis.session;/*** description: 工厂模式接口构建SqlSession的工厂*/
public interface SqlSessionFactory {/*** 打开一个session** return SqlSession*/SqlSession openSession();
}DefaultSqlSessionFactory.java package com.lino.mybatis.session.defaults;import com.lino.mybatis.executor.Executor;
import com.lino.mybatis.mapping.Environment;
import com.lino.mybatis.session.Configuration;
import com.lino.mybatis.session.SqlSession;
import com.lino.mybatis.session.SqlSessionFactory;
import com.lino.mybatis.session.TransactionIsolationLevel;
import com.lino.mybatis.transaction.Transaction;
import com.lino.mybatis.transaction.TransactionFactory;
import java.sql.SQLException;/*** description: 默认的SqlSessionFactory实现类*/
public class DefaultSqlSessionFactory implements SqlSessionFactory {private final Configuration configuration;public DefaultSqlSessionFactory(Configuration configuration) {this.configuration configuration;}Overridepublic SqlSession openSession() {Transaction tx null;try {final Environment environment configuration.getEnvironment();TransactionFactory transactionFactory environment.getTransactionFactory();tx transactionFactory.newTransaction(configuration.getEnvironment().getDataSource(), TransactionIsolationLevel.READ_COMMITTED, false);// 创建执行器final Executor executor configuration.newExecutor(tx);// 创建 DefaultSqlSessionreturn new DefaultSqlSession(configuration, executor);} catch (Exception e) {try {assert tx ! null;tx.close();} catch (SQLException ignore) {}throw new RuntimeException(Error opening session. Cause: e);}}
}工厂模式简单工厂是一种创建型设计模式其在父类中提供一个创建对象的方法允许子类决定实例对象的类型。场景介绍SqlSessionFactory 是获取会话的工厂每次我们使用 Mybatis 操作数据库的时候都会开启一个新的会话。 在会话工厂的实现中负责获取数据源环境配置信息、构建事务工厂、创建操作 SQL 的执行器并最终返回会话实现类。 同类设计SqlSessionFactory、ObjectFactory、MapperproxyFactory、DataSourceFactory
1.2 单例模式 Configuration.java package com.lino.mybatis.session;import com.lino.mybatis.binding.MapperRegistry;
import com.lino.mybatis.cache.Cache;
import com.lino.mybatis.cache.decorators.FifoCache;
import com.lino.mybatis.cache.impl.PerpetualCache;
import com.lino.mybatis.datasource.druid.DruidDataSourceFactory;
import com.lino.mybatis.datasource.pooled.PooledDataSourceFactory;
import com.lino.mybatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.lino.mybatis.executor.CachingExecutor;
import com.lino.mybatis.executor.Executor;
import com.lino.mybatis.executor.SimpleExecutor;
import com.lino.mybatis.executor.keygen.KeyGenerator;
import com.lino.mybatis.executor.parameter.ParameterHandler;
import com.lino.mybatis.executor.resultset.DefaultResultSetHandler;
import com.lino.mybatis.executor.resultset.ResultSetHandler;
import com.lino.mybatis.executor.statement.PreparedStatementHandler;
import com.lino.mybatis.executor.statement.StatementHandler;
import com.lino.mybatis.mapping.BoundSql;
import com.lino.mybatis.mapping.Environment;
import com.lino.mybatis.mapping.MappedStatement;
import com.lino.mybatis.mapping.ResultMap;
import com.lino.mybatis.plugin.Interceptor;
import com.lino.mybatis.plugin.InterceptorChain;
import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.factory.DefaultObjectFactory;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.wrapper.DefaultObjectWrapperFactory;
import com.lino.mybatis.reflection.wrapper.ObjectWrapperFactory;
import com.lino.mybatis.scripting.LanguageDriver;
import com.lino.mybatis.scripting.LanguageDriverRegistry;
import com.lino.mybatis.scripting.xmltags.XMLLanguageDriver;
import com.lino.mybatis.transaction.Transaction;
import com.lino.mybatis.transaction.jdbc.JdbcTransactionFactory;
import com.lino.mybatis.type.TypeAliasRegistry;
import com.lino.mybatis.type.TypeHandlerRegistry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;/*** description: 配置项*/
public class Configuration {/*** 环境*/protected Environment environment;/*** 是否使用自动生成键值对*/protected boolean useGeneratedKeys false;/*** 默认启用缓存,cacheEnabled true/false*/protected boolean cacheEnabled true;/*** 缓存机制默认不配置的情况是 SESSION*/protected LocalCacheScope localCacheScope LocalCacheScope.SESSION;/*** 映射注册机*/protected MapperRegistry mapperRegistry new MapperRegistry(this);/*** 映射的语句存在Map里*/protected final MapString, MappedStatement mappedStatements new HashMap(16);/*** 缓存存在Map里*/protected final MapString, Cache caches new HashMap(16);/*** 结果映射存在Map里*/protected final MapString, ResultMap resultMaps new HashMap(16);/*** 键值生成器存在Map里*/protected final MapString, KeyGenerator keyGenerators new HashMap(16);/*** 插件拦截器链*/protected final InterceptorChain interceptorChain new InterceptorChain();/*** 类型别名注册机*/protected final TypeAliasRegistry typeAliasRegistry new TypeAliasRegistry();/*** 脚本语言注册器*/protected final LanguageDriverRegistry languageRegistry new LanguageDriverRegistry();/*** 类型处理器注册机*/protected final TypeHandlerRegistry typeHandlerRegistry new TypeHandlerRegistry();/*** 对象工厂*/protected ObjectFactory objectFactory new DefaultObjectFactory();/*** 对象包装工厂*/protected ObjectWrapperFactory objectWrapperFactory new DefaultObjectWrapperFactory();/*** 准备资源列表*/protected final SetString loadedResources new HashSet();/*** 数据库ID*/protected String databaseId;//...}单例模式是一种创建型模式让你能够保证一个类只有一个实例并提供一个访问该实例的全局节点。场景介绍Configuration 就像狗皮膏药一样大单例贯穿整个会话的生命周期所有的配置对象。 映射、缓存、入参、出参、拦截器、注册机、对象工厂等都在 Configuration 配置项中初始化。并随着 SqlSessionFactorybuilder 构建阶段完成实例化操作。 同类场景ErrorContext、LogFactory、Configutation
1.3 建造者模式 ResultMap.java package com.lino.mybatis.mapping;import com.lino.mybatis.session.Configuration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;/*** description: 结果映射*/
public class ResultMap {private String id;private Class? type;private ListResultMapping resultMappings;private SetString mappedColumns;public ResultMap() {}public static class Builder {private ResultMap resultMap new ResultMap();public Builder(Configuration configuration, String id, Class? type, ListResultMapping resultMappings) {resultMap.id id;resultMap.type type;resultMap.resultMappings resultMappings;}public ResultMap build() {resultMap.mappedColumns new HashSet();// 添加 mappedColums 字段for (ResultMapping resultMapping : resultMap.resultMappings) {final String column resultMapping.getColumn();if (column ! null) {resultMap.mappedColumns.add(column.toUpperCase(Locale.ENGLISH));}}return resultMap;}}//...
}建造者模式使用多个简单的对象一步一步构建成一个复杂的对象这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。场景介绍关于建造者模式在 Mybatis 框架里的使用到处都是 XxxBuilder所有关于 XML 文件的解析到各类对象的封装都使用建造者以及建造者助手来完成对象的封装。 它的核心目的就是不希望把过多的关于对象的属性设置写到其他业务流程中而是用创建者的方式提供最佳的边界隔离。 同类场景SqlSesiionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder
二、类型结构型模式
2.1 适配器模式 Log.java package com.lino.mybatis.logging;/*** description: 日志接口*/
public interface Log {boolean isDebugEnabled();boolean isTraceEnabled();void error(String s, Throwable e);void error(String s);void debug(String s);void trace(String s);void warn(String s);
}Slf4jImpl.java package com.lino.mybatis.logging.slf4j;import com.lino.mybatis.logging.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** description: slf4j log 设计模式类不做实现*/
public class Slf4jImpl implements Log {public Slf4jImpl(String clazz) {Logger logger LoggerFactory.getLogger(clazz);}Overridepublic boolean isDebugEnabled() {return false;}Overridepublic boolean isTraceEnabled() {return false;}Overridepublic void error(String s, Throwable e) {}Overridepublic void error(String s) {}Overridepublic void debug(String s) {}Overridepublic void trace(String s) {}Overridepublic void warn(String s) {}
}适配器模式是一种结构型设计模式它能使接口不兼容的对象能够相互合作。场景介绍正是因为有太多的日志框架包括Log4j、Log4j2、Slf4J 等等而这些日志框架的使用接口又都各有差异为了统一这些日志工具的接口Mybatis 定义了一套统一的日志接口为所有的其他日志工具接口做相应的适配操作。同类场景主要集中在对日志的适配上Log 和 对应的实现类以及在 LogFactory 工厂方法中进行使用。
2.2 代理模式 MapperProxy.java package com.lino.mybatis.binding;import com.lino.mybatis.session.SqlSession;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;/*** description: 映射器代理类*/
public class MapperProxyT implements InvocationHandler, Serializable {private static final long serialVersionUID -6424540398559729838L;private SqlSession sqlSession;private final ClassT mapperInterface;private final MapMethod, MapperMethod methodCache;public MapperProxy(SqlSession sqlSession, ClassT mapperInterface, MapMethod, MapperMethod methodCache) {this.sqlSession sqlSession;this.mapperInterface mapperInterface;this.methodCache methodCache;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);} else {final MapperMethod mapperMethod cacheMapperMethod(method);return mapperMethod.execute(sqlSession, args);}}/*** 去缓存中找MapperMethod*/private MapperMethod cacheMapperMethod(Method method) {MapperMethod mapperMethod methodCache.get(method);if (mapperMethod null) {mapperMethod new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());methodCache.put(method, mapperMethod);}return mapperMethod;}
}代理模式是一种结构型模式让你能够提供对象的替代品或其占位符。代理控制着对原对象的访问并允许在将请求提交给对象前进行一些处理。场景介绍没有代理模式就不会有各类的框架存在。就像 Mybatis 中的 MybatisProxy 映射器代理实现类它所实现的功能就是帮助我们完成 DAO 接口的具体实现类的方法操作你的任何一个配置的 DAO 接口所调用的 CRUD 方法都会被 MapperProxy 接管调用到方法执行器等一系列操作并返回最终的数据的数据库执行结果。同类场景DriverProxy、Plugin、Invoker、MapperProxy
2.3 组合模式 SqlNode.java package com.lino.mybatis.scripting.xmltags;/*** description: SQL 节点*/
public interface SqlNode {/*** 应用动态上下文** param context 动态上下文* return boolean*/boolean apply(DynamicContext context);
}IfSqlNode.java package com.lino.mybatis.scripting.xmltags;/*** description: IF SQL 节点*/
public class IfSqlNode implements SqlNode {private ExpressionEvaluator evaluator;private String test;private SqlNode contents;public IfSqlNode(SqlNode contents, String test) {this.test test;this.contents contents;this.evaluator new ExpressionEvaluator();}Overridepublic boolean apply(DynamicContext context) {// 如果满足条件则apply并返回trueif (evaluator.evaluateBoolean(test, context.getBindings())) {contents.apply(context);return true;}return false;}
}XMLScriptBuilder.java package com.lino.mybatis.scripting.xmltags;import com.lino.mybatis.builder.BaseBuilder;
import com.lino.mybatis.mapping.SqlSource;
import com.lino.mybatis.scripting.defaults.RawSqlSource;
import com.lino.mybatis.session.Configuration;
import org.dom4j.Element;
import org.dom4j.Node;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** description: XML脚本构建器*/
public class XMLScriptBuilder extends BaseBuilder {private Element element;private boolean isDynamic;private Class? parameterType;private final MapString, NodeHandler nodeHandlerMap new HashMap();public XMLScriptBuilder(Configuration configuration, Element element, Class? parameterType) {super(configuration);this.element element;this.parameterType parameterType;initNodeHandlerMap();}private void initNodeHandlerMap() {// 9种实现其中2种 trim/where/set/foreach/if/choose/when/otherwise/bindnodeHandlerMap.put(trim, new TrimHandler());nodeHandlerMap.put(if, new IfHandler());}public SqlSource parseScriptNode() {ListSqlNode contents parseDynamicTags(element);MixedSqlNode rootSqlNode new MixedSqlNode(contents);SqlSource sqlSource null;if (isDynamic) {sqlSource new DynamicSqlSource(configuration, rootSqlNode);} else {sqlSource new RawSqlSource(configuration, rootSqlNode, parameterType);}return sqlSource;}private ListSqlNode parseDynamicTags(Element element) {ListSqlNode contents new ArrayList();ListNode children element.content();for (Node child : children) {if (child.getNodeType() Node.TEXT_NODE || child.getNodeType() Node.CDATA_SECTION_NODE) {String data child.getText();TextSqlNode textSqlNode new TextSqlNode(data);if (textSqlNode.isDynamic()) {contents.add(textSqlNode);isDynamic true;} else {contents.add(new StaticTextSqlNode(data));}} else if (child.getNodeType() Node.ELEMENT_NODE) {String nodeName child.getName();NodeHandler handler nodeHandlerMap.get(nodeName);if (handler null) {throw new RuntimeException(Unknown element nodeName in SQL statement.);}handler.handleNode(element.element(child.getName()), contents);isDynamic true;}}return contents;}private interface NodeHandler {void handleNode(Element nodeToHandle, ListSqlNode targetContents);}private class TrimHandler implements NodeHandler {Overridepublic void handleNode(Element nodeToHandle, ListSqlNode targetContents) {ListSqlNode contents parseDynamicTags(nodeToHandle);MixedSqlNode mixedSqlNode new MixedSqlNode(contents);String prefix nodeToHandle.attributeValue(prefix);String prefixOverrides nodeToHandle.attributeValue(prefixOverrides);String suffix nodeToHandle.attributeValue(suffix);String suffixOverrides nodeToHandle.attributeValue(suffixOverrides);TrimSqlNode trim new TrimSqlNode(configuration, mixedSqlNode, prefix, prefixOverrides, suffix, suffixOverrides);targetContents.add(trim);}}private class IfHandler implements NodeHandler {Overridepublic void handleNode(Element nodeToHandle, ListSqlNode targetContents) {ListSqlNode contents parseDynamicTags(nodeToHandle);MixedSqlNode mixedSqlNode new MixedSqlNode(contents);String test nodeToHandle.attributeValue(test);IfSqlNode ifSqlNode new IfSqlNode(mixedSqlNode, test);targetContents.add(ifSqlNode);}}
}Activity_Mapper.xml select idqueryActivityById parameterTypecom.lino.mybatis.test.po.Activity resultMapactivityMapSELECT activity_id, activity_name, activity_desc, create_time, update_timeFROM activitytrim prefixwhere prefixOverridesAND | OR suffixOverridesandif testnull ! activityIdactivity_id #{activityId}/if/trim
/select组合模式是一种结构型设计模式你可以使用它将对象组合成树状结构并且能独立使用对象一样使用它们。场景介绍在 Mybatis XML 动态的 SQL 配置中共提供了9种trim/where/set/foreach/if/choose/when/otherwise/bind标签的使用让使用者可以组合出各类场景的 SQL 语句。而 SqlNode 接口的实现就是每一个组合结构种的规则节点通过规则节点的组装完成一颗规则树组合模式的使用。同类场景主要体现在对各类 SQL 标签的解析上以实现 SqlNode 接口的各个子类为主。
2.4 装饰器模式 Congiguration.java package com.lino.mybatis.session;import com.lino.mybatis.binding.MapperRegistry;
import com.lino.mybatis.cache.Cache;
import com.lino.mybatis.cache.decorators.FifoCache;
import com.lino.mybatis.cache.impl.PerpetualCache;
import com.lino.mybatis.datasource.druid.DruidDataSourceFactory;
import com.lino.mybatis.datasource.pooled.PooledDataSourceFactory;
import com.lino.mybatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.lino.mybatis.executor.CachingExecutor;
import com.lino.mybatis.executor.Executor;
import com.lino.mybatis.executor.SimpleExecutor;
import com.lino.mybatis.executor.keygen.KeyGenerator;
import com.lino.mybatis.executor.parameter.ParameterHandler;
import com.lino.mybatis.executor.resultset.DefaultResultSetHandler;
import com.lino.mybatis.executor.resultset.ResultSetHandler;
import com.lino.mybatis.executor.statement.PreparedStatementHandler;
import com.lino.mybatis.executor.statement.StatementHandler;
import com.lino.mybatis.mapping.BoundSql;
import com.lino.mybatis.mapping.Environment;
import com.lino.mybatis.mapping.MappedStatement;
import com.lino.mybatis.mapping.ResultMap;
import com.lino.mybatis.plugin.Interceptor;
import com.lino.mybatis.plugin.InterceptorChain;
import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.reflection.factory.DefaultObjectFactory;
import com.lino.mybatis.reflection.factory.ObjectFactory;
import com.lino.mybatis.reflection.wrapper.DefaultObjectWrapperFactory;
import com.lino.mybatis.reflection.wrapper.ObjectWrapperFactory;
import com.lino.mybatis.scripting.LanguageDriver;
import com.lino.mybatis.scripting.LanguageDriverRegistry;
import com.lino.mybatis.scripting.xmltags.XMLLanguageDriver;
import com.lino.mybatis.transaction.Transaction;
import com.lino.mybatis.transaction.jdbc.JdbcTransactionFactory;
import com.lino.mybatis.type.TypeAliasRegistry;
import com.lino.mybatis.type.TypeHandlerRegistry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;/*** description: 配置项*/
public class Configuration {/*** 生产执行器** param transaction 事务* return 执行器*/public Executor newExecutor(Transaction transaction) {Executor executor new SimpleExecutor(this, transaction);// 配置开启缓存,创建 CachingExecutor(默认就是有缓存)装饰着模式if (cacheEnabled) {executor new CachingExecutor(executor);}return executor;}}装饰器模式是一种结构型设计模式允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。场景介绍Mybatis 的所有 SQL 操作都是经过 SqlSession 会话调用 SimpleExecutor 简单实现的执行器完成的而一级缓存的操作也是在简单执行器中处理。那么这里二级缓存因为是基于二级缓存刷新操作的所以在实现上通过创建一个缓存执行器包装简单执行器的处理逻辑实现二级缓存操作。那么这里用到的就是装饰器模式也叫俄罗斯套娃模式。同类场景主要提前在 Cache 缓存接口的实现和 CachingExecutor 执行器中。
三、类型行为型模式
3.1 模板模式 BaseExecutor.java package com.lino.mybatis.executor;import com.lino.mybatis.cache.CacheKey;
import com.lino.mybatis.cache.impl.PerpetualCache;
import com.lino.mybatis.mapping.BoundSql;
import com.lino.mybatis.mapping.MappedStatement;
import com.lino.mybatis.mapping.ParameterMapping;
import com.lino.mybatis.reflection.MetaObject;
import com.lino.mybatis.session.Configuration;
import com.lino.mybatis.session.LocalCacheScope;
import com.lino.mybatis.session.ResultHandler;
import com.lino.mybatis.session.RowBounds;
import com.lino.mybatis.transaction.Transaction;
import com.lino.mybatis.type.TypeHandlerRegistry;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;/*** description: 执行器抽象基类*/
public abstract class BaseExecutor implements Executor {Overridepublic E ListE query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {if (closed) {throw new RuntimeException(Executor was closed.);}// 清理局部缓存查询堆栈为0则清理。queryStack 避免递归调用清理if (queryStack 0 ms.isFlushCacheRequired()) {clearLocalCache();}ListE list;try {queryStack;// 根据cacheKey从localCache中查询数据list resultHandler null ? (ListE) localCache.getObject(key) : null;if (list null) {list queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack 0) {if (configuration.getLocalCacheScope() LocalCacheScope.STATEMENT) {clearLocalCache();}}return list;}}SimpleExecutor.java package com.lino.mybatis.executor;import com.lino.mybatis.executor.statement.StatementHandler;
import com.lino.mybatis.mapping.BoundSql;
import com.lino.mybatis.mapping.MappedStatement;
import com.lino.mybatis.session.Configuration;
import com.lino.mybatis.session.ResultHandler;
import com.lino.mybatis.session.RowBounds;
import com.lino.mybatis.transaction.Transaction;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;/*** description: 简单执行器*/
public class SimpleExecutor extends BaseExecutor {public SimpleExecutor(Configuration configuration, Transaction transaction) {super(configuration, transaction);}Overrideprotected int doUpdate(MappedStatement ms, Object parameter) throws SQLException {Statement stmt null;try {Configuration configuration ms.getConfiguration();// 新建一个 StatementHandlerStatementHandler handler configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);// 准备语句stmt prepareStatement(handler);// StatementHandler.updatereturn handler.update(stmt);} finally {closeStatement(stmt);}}Overrideprotected E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt null;try {Configuration configuration ms.getConfiguration();// 新建一个 StatementHandlerStatementHandler handler configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);// 准备语句stmt prepareStatement(handler);// 返回结果return handler.query(stmt, resultHandler);} finally {closeStatement(stmt);}}private Statement prepareStatement(StatementHandler handler) throws SQLException {Statement stmt;Connection connection transaction.getConnection();// 准备语句stmt handler.prepare(connection);handler.parameterize(stmt);return stmt;}
}模板模式是一种行为设计模式它在超类中定义了一个算法的框架允许子类在不修改结构的情况下重写算法的特定步骤。场景介绍只要存在一系列可被标准定义的流程在流程的步骤大部分是通用逻辑只有一少部分是需要子类实现的那么通常会采用模板模式来定义出这个标准的流程。就像 Mybatis 的 BaseExecutor 就是一个用于定义模板模式的抽象类在这个类中把查询、修改的操作都定义出了一套标准的流程。同类场景BaseExecutor、SimpleExecutor、BaseTypeHandler
3.2 策略模式 TypeHandler.java package com.lino.mybatis.type;import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** description: 类型处理器*/
public interface TypeHandlerT {/*** 设置参数** param ps 预处理语言* param i 次数* param parameter 参数对象* param jdbcType JDBC类型* throws SQLException SQL异常*/void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;/*** 获取结果** param rs 结果列表* param columnName 列名* return T 结果* throws SQLException*/T getResult(ResultSet rs, String columnName) throws SQLException;/*** 获取结果** param rs 结果列表* param columnIndex 列的索引* return T 结果* throws SQLException*/T getResult(ResultSet rs, int columnIndex) throws SQLException;
}LongTypeHandler.java package com.lino.mybatis.type;import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** description: Long类型处理器* author: lingjian* createDate: 2022/11/11 13:59*/
public class LongTypeHandler extends BaseTypeHandlerLong {Overrideprotected void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {ps.setLong(i, parameter);}Overrideprotected Long getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getLong(columnName);}Overrideprotected Long getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return rs.getLong(columnIndex);}
}策略模式是一种行为设计模式它能定义一系列算法并将每种算法分别放入独立的类中以便算法的对象能够互相替换。场景介绍在 Mybatis 处理 JDBC 执行后返回的结果时需要按照不同的类型获取对应的值这样就可以避免大量的 if 判断。所以这里基于 TypeHandler 接口对每个参数类型分别做了自己的策略实现。同类场景PooledDataSource\UnpooledDataSource、BatchExecutor\ResuseExecutor\SimpleExecutor\CachingExecutor、LongTypeHandler\StringTypeHandler\DateTypeHandler
3.3 迭代器模式 PropertyTokenizer.java package com.lino.mybatis.reflection.property;import java.util.Iterator;/*** description: 属性分解标记*/
public class PropertyTokenizer implements IterablePropertyTokenizer, IteratorPropertyTokenizer {// 例子班级[0].学生.成绩/*** 属性名称班级*/private String name;/*** 属性对象名称班级[0]*/private String indexedName;/*** 属性索引0*/private String index;/*** 子属性学生*/private String children;public PropertyTokenizer(String fullName) {// 班级[0].学生.成绩找.int delim fullName.indexOf(.);if (delim -1) {name fullName.substring(0, delim);children fullName.substring(delim 1);} else {// 找不到.的话取全部部分name fullName;children null;}indexedName name;// 把中括号里的数字解析出来delim name.indexOf([);if (delim -1) {index name.substring(delim 1, name.length() - 1);name name.substring(0, delim);}}Overridepublic IteratorPropertyTokenizer iterator() {return this;}Overridepublic boolean hasNext() {return children ! null;}Overridepublic void remove() {throw new UnsupportedOperationException(Remove is not supported, as it has no meaning in the context of properties.);}Overridepublic PropertyTokenizer next() {return new PropertyTokenizer(children);}public String getName() {return name;}public String getIndexedName() {return indexedName;}public String getIndex() {return index;}public String getChildren() {return children;}
}迭代器模式是一种行为设计模式让你能在不暴露集合底层表现形式的情况下遍历集合中所有的元素。场景介绍PropertyTokenizer 是用于 Mybatis 框架 MetaObject 反射工具包下用于解析对象关系的迭代操作。这个类在 Mybatis 框架中使用的非常频繁包括解析数据源配置信息并填充到数据源类上以及参数的解析、对象的设置都会使用到这个类。同类场景PropertyTokenizer