MyBatis-Plugins 的创建流程与执行顺序
一、插件的解析,所有插件都会被添加到 InterceptorChain 类中,用于后续处理
org.apache.ibatis.builder.xml.XMLConfigBuilder
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
String interceptor = child.getStringAttribute("interceptor");
Properties properties = child.getChildrenAsProperties();
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
interceptorInstance.setProperties(properties);
configuration.addInterceptor(interceptorInstance);
}
}
}
org.apache.ibatis.session.Configuration
public void addInterceptor(Interceptor interceptor) {
interceptorChain.addInterceptor(interceptor);
}
二、四大对象的创建顺序,都会经过 interceptorChain.pluginAll() 进行处理
1.Executor,SQL语句执行器
org.apache.ibatis.session.Configuration
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;
}
2.ParameterHandler,参数处理器
org.apache.ibatis.executor.statement.BaseStatementHandler
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
org.apache.ibatis.session.Configuration
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
3.ResultSetHandler,结果集处理器
org.apache.ibatis.executor.statement.BaseStatementHandler
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
org.apache.ibatis.session.Configuration
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;
}
4.StatementHandler,SQL语句处理器
org.apache.ibatis.executor.SimpleExecutor
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
org.apache.ibatis.session.Configuration
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
三、多个不同类型插件的执行顺序
org.apache.ibatis.executor.SimpleExecutor
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
// 3.执行 SQL 语句,封装结果集,ResultSetHandler 拦截插件执行
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
} private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
// 1.准备语句,StatementHandler 拦截插件执行
stmt = handler.prepare(connection, transaction.getTimeout());
// 2.SQL 语句参数处理,ParameterHandler 拦截插件执行
handler.parameterize(stmt);
return stmt;
}
四、多个相同类型插件的执行顺序,以 StatementHandler 为例
1.创建顺序,按照配置顺序层层代理,最后配置的插件为最外层代理
配置了两个插件
<plugins>
<plugin interceptor="com.plugins.ExamplePlugin"></plugin>
<plugin interceptor="com.plugins.ExamplePlugin2"></plugin>
</plugins>
1.1.准备创建

1.2.最开始要执行的对象

1.3.开始创建

1.4.创建完毕

2.执行顺序,按照配置顺序倒序执行
2.1.第一次执行,ExamplePlugin2

2.2.第二次执行,ExamplePlugin

2.3.最终执行

3.示意图

MyBatis-Plugins 的创建流程与执行顺序的更多相关文章
- 步步深入:MySQL架构总览->查询执行流程->SQL解析顺序
前言: 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一篇博文了. 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序来 ...
- MySQL架构总览->查询执行流程->SQL解析顺序
Reference: https://www.cnblogs.com/annsshadow/p/5037667.html 前言: 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后 ...
- 步步深入MySQL:架构->查询执行流程->SQL解析顺序!
一.前言 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一篇博文了. 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序 ...
- Unity脚本在层级面板中的执行顺序测试1
第二篇测试循环时和动态创建时的调用顺序:LINK 测试版本Unity4.6.因为新版本对Transform的排序做了改变,所以不排除旧版本的测试结果不一样.测试时,使用Awake中添加Debug.lo ...
- python—day15 包的认识、执行顺序、执行流程、循环导入、包的导入、绝对、相对导入
一.包的认识 包通过文件夹来管理一系列功能相近的模块 包:一系列模块的集合体 重点:包中一定有一个专门用来管理包中所有模块的文件 包名:存放一系列模块的文件夹名字 包名(包对象)存放的是管理模 ...
- Python流程控制-1 顺序执行
流程控制指的是代码运行逻辑.分支走向.循环控制,是真正体现我们程序执行顺序的操作.流程控制一般分为顺序执行.条件判断和循环控制. 顺序执行 Python代码在执行过程中,遵循下面的基本原则: 普通语句 ...
- mirantis fuel puppet执行顺序 和 对整个项目代码的执行流程理解
stage执行顺序 stage {'zero': } -> stage {'first': } -> stage {'openstack-custom-repo': } -> sta ...
- 创建HttpFilter与理解多个Filter代码的执行顺序
1.自定义的HttpFilter,实现Filter接口 HttpFilter package com.aff.filter; import java.io.IOException; import ja ...
- java-mybaits-013-mybatis-Interceptor-拦截器执行顺序
一.概述 已知拦截器能够拦截四种类型:Executor.ParameterHandler.ResultSetHandler.StatementHandler. 1.1.不同类型拦截器的执行顺序 背景: ...
随机推荐
- Python操作Memcached
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度.Memcached ...
- SPOJ QTREE-Query on a tree-树链剖分-边权
用每个点代表父节点到此点的边.建立一一映射后就可以用点权的方法处理了. 注意的是路径两端节点的处理 #include <cstdio> #include <algorithm> ...
- Elasticsearch 聚合统计与SQL聚合统计语法对比(一)
Es相比关系型数据库在数据检索方面有着极大的优势,在处理亿级数据时,可谓是毫秒级响应,我们在使用Es时不仅仅进行简单的查询,有时候会做一些数据统计与分析,如果你以前是使用的关系型数据库,那么Es的数据 ...
- php+redis配置
系统环境: win10+phpstudy+lamp 安装扩展 php5.6.4 =>下载地址:http://windows.php.net/downloads/pecl/releases/red ...
- phpcms 手机门户配置注意事项
设置域名解析后,服务器apache,iis,nginx等,设置虚拟服务器时, 如下,只设置index.php为默认入口文件: 默认pc站为index.html为默认访问文件! pc与wap站,绑定目录 ...
- MT【298】双参数非齐次
若函数$f(x)=x^2+(\dfrac{1}{3}+a)x+b$在$[-1,1]$上有零点,则$a^2-3b$的最小值为_____ 分析:设零点为$x_0$,则$b=-x^2_0-(\dfrac{1 ...
- MT【253】仿射和蒙日圆
如图,设点$M(x_0,y_0)$是椭圆$C:\dfrac{x^2}{2}+y^2=1$上一点,从原点$O$向圆$M:(x-x_0)^2+(y-y_0)^2=\dfrac{2}{3}$作两条切线分别与 ...
- 【BZOJ3165】[HEOI2013]Segment(李超线段树)
[BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cst ...
- JS日期选择器
浏览器自带 浏览器自带日期控件,使用<input type="date">时,点击后会弹出. 1:EDGE 2:火狐 3:谷歌 三种都不一样.略胜于无 练习 模仿火狐 ...
- 537. Complex Number Multiplication
题目大意: 给出a, b两个用字符串表示的虚数,求a*b 题目思路: 偷了个懒,Python3的正则表达式匹配了一下,当然acm里肯定是不行的 class Solution: def complexN ...