单例模式
利用static的特性,类加载器只会加载一次同时上锁的特性,实现懒加载.
public abstract class VFS {
private static class VFSHolder {
static final VFS INSTANCE = createVFS();
@SuppressWarnings("unchecked")
static VFS createVFS() {
// Try the user implementations first, then the built-ins
// 优先使用用户自定义的VFS 实现, 如没有自定义VFS 实现,则使用MyBatis 提供的VFS 实现
List<Class<? extends VFS>> impls = new ArrayList<>();
impls.addAll(USER_IMPLEMENTATIONS);
impls.addAll(Arrays.asList((Class<? extends VFS>[]) IMPLEMENTATIONS));
// Try each implementation class until a valid one is found
//遍历集合,依次实例化VFS 对象并检测VFS 对象是否有效,一旦得到有效的VFS 对象,则结束循环
VFS vfs = null;
for (int i = 0; vfs == null || !vfs.isValid(); i++) {
Class<? extends VFS> impl = impls.get(i);
try {
vfs = impl.getDeclaredConstructor().newInstance();
if (!vfs.isValid() && log.isDebugEnabled()) {
log.debug("VFS implementation " + impl.getName()
+ " is not valid in this environment.");
}
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
log.error("Failed to instantiate " + impl, e);
return null;
}
}
if (log.isDebugEnabled()) {
log.debug("Using VFS adapter " + vfs.getClass().getName());
}
return vfs;
}
}
/**
* Get the singleton {@link VFS} instance. If no {@link VFS} implementation can be found for the current environment,
* then this method returns null.
*
* @return single instance of VFS
*/
public static VFS getInstance() {
return VFSHolder.INSTANCE;
}
}
适配器模式
针对不同的log组件统一只进行4种日志处理,trace 、debug 、
warn 、error 四个级别
public final class LogFactory {
/**
* Marker to be used by logging implementations that support markers.
*/
public static final String MARKER = "MYBATIS";
// 记录当前使用的第二方日志组件所对应的适配器的构造方法
private static Constructor<? extends Log> logConstructor;
static {
//下面会针对每种日志组件调用tr yimplementation ( )方法进行尝试加载,具体调用顺序是:
//useSlf4jLogging ()一> useCommonsLogging ()一> useLog4J2Logging ()一〉
// useLog 4JLogging()--> useJdkLogging() -> useNoLogging()
tryImplementation(LogFactory::useSlf4jLogging);
tryImplementation(LogFactory::useCommonsLogging);
tryImplementation(LogFactory::useLog4J2Logging);
tryImplementation(LogFactory::useLog4JLogging);
tryImplementation(LogFactory::useJdkLogging);
tryImplementation(LogFactory::useNoLogging);
}
}
代理模式
public final class ConnectionLogger extends BaseJdbcLogger implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
try {
//如调用的是从Object继承的方法,则直接调用,不做任何其他处理
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
//如果调用的是prepareStatement ()方法、prepareCall ()方法或createStatement()方法,
//则在创建相应Statement 对象后,为其创建代理对象并返回该代理对象
if ("prepareStatement".equals(method.getName()) || "prepareCall".equals(method.getName())) {
// 日志输出
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
//为该PreparedStatement 对象创建代理对象
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else if ("createStatement".equals(method.getName())) {
Statement stmt = (Statement) method.invoke(connection, params);
stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else {
return method.invoke(connection, params);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
/**
* Creates a logging version of a connection.
*
* @param conn
* the original connection
* @param statementLog
* the statement log
* @param queryStack
* the query stack
* @return the connection with logging
*/
public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
//使用JDK 动态代理的方式创建代理对象
InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
ClassLoader cl = Connection.class.getClassLoader();
return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
}
}
责任链模式
org.apache.ibatis.logging.jdbc.ConnectionLogger#invoke方法,针对不同的操作处理,交给不同的Logger处理
public final class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
//调用了EXECUTE_METHODS集合中的方法
if (EXECUTE_METHODS.contains(method.getName())) {
if (isDebugEnabled()) {
// 日志输出,输出的是参数值以及参数类型
debug("Parameters: " + getParameterValueString(), true);
}
// 清空BaseJdbcLogger 中定义的三个column *集合
clearColumnInfo();
if ("executeQuery".equals(method.getName())) {
//如果调用executeQuery ()方法, 则为ResultSet 创建代理对象
ResultSet rs = (ResultSet) method.invoke(statement, params);
return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
} else {
return method.invoke(statement, params);
}
} else if (SET_METHODS.contains(method.getName())) {
//如果调用SET_METHODS 集合中的方法, 则通过setColumn ()方法记录到BaseJdbcLogger 中定义的三个column *集合
if ("setNull".equals(method.getName())) {
setColumn(params[0], null);
} else {
setColumn(params[0], params[1]);
}
return method.invoke(statement, params);
} else if ("getResultSet".equals(method.getName())) {
//如果调用getResultSet ()方法,则为ResultSet创建代理对象
ResultSet rs = (ResultSet) method.invoke(statement, params);
return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
} else if ("getUpdateCount".equals(method.getName())) {
//如果调用getUpdateCount ( )方法,则通过日志框架输出其结果
int updateCount = (Integer) method.invoke(statement, params);
if (updateCount != -1) {
debug(" Updates: " + updateCount, false);
}
return updateCount;
} else {
return method.invoke(statement, params);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
/**
* Creates a logging version of a PreparedStatement.
*
* @param stmt - the statement
* @param statementLog - the statement log
* @param queryStack - the query stack
* @return - the proxy
*/
public static PreparedStatement newInstance(PreparedStatement stmt, Log statementLog, int queryStack) {
InvocationHandler handler = new PreparedStatementLogger(stmt, statementLog, queryStack);
ClassLoader cl = PreparedStatement.class.getClassLoader();
return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
}
}
工厂模式
每个数据源工厂构造不同的数据源
public interface DataSourceFactory {
//设置Data Source 的相关属性,一般紧跟在初始化完成之后
void setProperties(Properties props);
//获取DataSource 对象
DataSource getDataSource();
}
public class UnpooledDataSourceFactory implements DataSourceFactory {
public UnpooledDataSourceFactory() {
this.dataSource = new UnpooledDataSource();
}
}
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
public PooledDataSourceFactory() {
this.dataSource = new PooledDataSource();
}
}
装饰者模式
组
组合模式
封装成树
public class XMLScriptBuilder extends BaseBuilder {
public SqlSource parseScriptNode() {
//首先判断当前的节点是不是有动态SQL ,动态SQL 会包括占位符或是动态SQL 的相关节点
MixedSqlNode rootSqlNode = parseDynamicTags(context);
SqlSource sqlSource;
//根据是否是动态SQL , 创建相应的SqlSource 对象
if (isDynamic) {
sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
} else {
sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
}
return sqlSource;
}
protected MixedSqlNode parseDynamicTags(XNode node) {
//用于记录生成的SqlNode 集合
List<SqlNode> contents = new ArrayList<>();
//获取SelectKey 的所有子节点
NodeList children = node.getNode().getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
//创建XNode ,该过程会将能解析掉的” ${} ” 都解析掉
XNode child = node.newXNode(children.item(i));
if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
String data = child.getStringBody("");
TextSqlNode textSqlNode = new TextSqlNode(data);
//解析SQL 语句,如果含有未解析的”${}”占位符,则为动态SQL
if (textSqlNode.isDynamic()) {
contents.add(textSqlNode);
// 标记为动态SQL 语句
isDynamic = true;
} else {
contents.add(new StaticTextSqlNode(data));
}
} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
//如果子节点是一个标签,那么一定是动态SQL ,并且根据不同的动态标签生成不同的NodeHandler
String nodeName = child.getNode().getNodeName();
//根据标签名称获取对应 的NodeHandler 对象
//处理where之类
NodeHandler handler = nodeHandlerMap.get(nodeName);
if (handler == null) {
throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
}
//处理动态SQL ,并将解析得到的SqlNode 对象放入contents 集合中保存
handler.handleNode(child, contents);
isDynamic = true;
}
}
// SqlNode 集合包装成一个MixedSqlNode
return new MixedSqlNode(contents);
}
}
public class MixedSqlNode implements SqlNode {
private final List<SqlNode> contents;
public MixedSqlNode(List<SqlNode> contents) {
this.contents = contents;
}
@Override
public boolean apply(DynamicContext context) {
contents.forEach(node -> node.apply(context));
return true;
}
}
public class DynamicSqlSource implements SqlSource {
@Override
public BoundSql getBoundSql(Object parameterObject) {
// 创建DynamicContext 对象, parameterObject 是用户传入的实参
DynamicContext context = new DynamicContext(configuration, parameterObject);
//通过调用rootSqlNode.apply ()方法调用整个树形结构中全部SqlNode. apply ()方法,读者可以
// 体会一下组合设计模式的好处。每个SqlNode 的apply ()方法都将解析得到的SQL 语句片段追加到
// context 中, 最终通过context.getSql()得到完整的SQL 语句
rootSqlNode.apply(context);
//创建SqlSourceBuilder ,解析参数属性,并将SQL 语句中的”#{ ) ” 占位符替换成” ? ” 占位符
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
//创建BoundSql 对象,并将DynamicContext.bindings 中的参数信息复制到其additionalParameters 集合中保存
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
context.getBindings().forEach(boundSql::setAdditionalParameter);
return boundSql;
}
}
策略模式
策略模式一
public class RoutingStatementHandler implements StatementHandler {
//底层封装的真正的StatementHandler 对象
private final StatementHandler delegate;
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
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());
}
}
}
策略模式二
摸吧
模板模式
交给子类实现