博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MyBatis 插件的作用点
阅读量:6293 次
发布时间:2019-06-22

本文共 3048 字,大约阅读时间需要 10 分钟。

1. 前言

我们自定义的插件在 MyBatis 中,可以作用的对象默认只有 4 个,分别是 ParameterHandler,ResultSetHandler, StatementHandler 和 Executor 接口的实现类的对象。

MyBatis 启动时会加载解析配置文件,我们自定义的拦截器也在这时被加载解析,并被放入 Configuration 类对象的 InterceptorChain 属性中。这个 InterceptorChain 中有一个 pluginAll 方法,通过上一篇文章分析得知该方法是给默认作用的 4 个接口实现类对象生成代理对象的入口方法。具体怎么生成的请看xxxxxxxx

2. 入口分析

ParameterHandler,ResultSetHandler, StatementHandler 和 Executor 接口的实现类的对象的代理对象生成入口对应 Configuration 类中的 4 个方法。如下:

// 返回 ParameterHandler 的代理对象  public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {    ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);    // 作用点    parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);    return parameterHandler;  }  // 返回 ResultSetHandler 的代理对象  public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,      ResultHandler resultHandler, BoundSql boundSql) {    ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);    // 作用点    resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);    return resultSetHandler;  }  // 返回 StatementHandler 的代理对象  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {      // RoutingSatatementHandler是个包装类      StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);      // 作用点      statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);    return statementHandler;  }  // 返回 Executor 的代理对象  public Executor newExecutor(Transaction transaction, ExecutorType executorType) {    executorType = executorType == null ? defaultExecutorType : executorType;    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;    Executor executor;    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);    }    if (cacheEnabled) {      executor = new CachingExecutor(executor);    }    // 作用点    executor = (Executor) interceptorChain.pluginAll(executor);    return executor;  }  复制代码

3. 总结

上面 4 个方法中,都有调用 interceptorChain 的 pluginAll 方法(见上面代码中 “作用点” 的地方),给目标对象生成代理对象。所以只要目标对象有匹配的拦截器, 我们每次在新建目标对象时都要利用 JDK 动态代理重新生成代理对象。比如 Executor 的实现类对象和 SqlSession 对象是绑定的。每次一个 Http 请求进来,创建 SqlSession 对象时,会创建 Executor 的对象,这个时候如果有适配的拦截器,就会被代理。有人可能会觉得,并发量大的时候是不是对性能有影响。个人觉得可以不用考虑。单次调用,代理还是不代理对性能的影响可以忽略。

推荐阅读:

动态代理方案性能对比:

历史文章:

谈谈 MyBatis 的插件化设计:

MyBatis 的插件对象如何创建出来的:

转载于:https://juejin.im/post/5cc118356fb9a032060c2b10

你可能感兴趣的文章
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数详解
查看>>
.NET MVC-去掉验证
查看>>
Logstash为什么那么慢?—— json序列化
查看>>
OSSEC配置文件ossec.conf中添加mysql服务
查看>>
排列与组合的一些定理(二)
查看>>
Apache RocketMQ Meetup深圳首秀 引开源爱好者追捧
查看>>
法国拟将雷诺与日产合并 代表团抵日进行谈判
查看>>
京津冀青少年网球分级赛总决赛开打 118名选手对决
查看>>
济南交警推出《酒驾整治日历》酒驾为每日必查项
查看>>
失手打死请自己吃饭的酒友 嫌疑人在深圳落网
查看>>
数据分析师常用的十种数据分析思路,你都知道吗?
查看>>
特斯拉Model3交付危机:周产5000辆仍需排队一年,造空者花式补刀
查看>>
客户端单周发版下的多分支自动化管理与实践
查看>>
Flutter初体验(二)—— 创建第一个Flutter APP
查看>>
「起点订阅页」Checkbox 美化引发的蝴蝶效应
查看>>
Swift iOS : 模糊化
查看>>
Android 应用防止被二次打包指南
查看>>
高级篇:独立开发者 5 分钟入门 ASO
查看>>
深度有趣 | 18 二次元头像生成
查看>>
Android P 凹口屏支持,打造全面屏体验
查看>>