阿里p7大神详细讲解Mybatis插件机制(植入、执行插件逻辑,分页插件)

本文详细讲解了MyBatis插件机制,包括插件植入和执行逻辑,通过分析Executor、ParameterHandler、ResultSetHandler和StatementHandler的拦截点。并实现了一个简单的分页插件,演示了如何利用插件实现功能拓展,以增强MyBatis框架的能力。
摘要由CSDN通过智能技术生成

插件机制

一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的
好处是显而易见的,一是增加了框架的灵活性。二是开发者可以结合实际需求,对框架进行
拓展,使其能够更好的工作。以 MyBatis 为例,我们可基于 MyBatis 插件机制实现分页、
分表,监控等功能。由于插件和业务无关,业务也无法感知插件的存在。因此可以无感植入
插件,在无形中增强功能。
开发 MyBatis 插件需要对 MyBatis 比较深了解才行,一般来说最好能够掌握 MyBatis
的源码,门槛相对较高。本篇文章在分析完 MyBatis 插件机制后,会手写一个简单的分页
插件,以帮助大家更好的掌握 MyBatis 插件的编写。

1、插件机制原理

我们在编写插件时,除了需要让插件类实现 Interceptor 接口外,还需要通过注解标注
该插件的拦截点。所谓拦截点指的是插件所能拦截的方法,MyBatis 所允许拦截的方法如
下:

  1. Executor: update, query, flushStatements, commit, rollback,
    getTransaction, close, isClosed
  2. ParameterHandler: getParameterObject, setParameters
  3. ResultSetHandler: handleResultSets, handleOutputParameters
  4. StatementHandler: prepare, parameterize, batch, update, query

如果我们想要拦截 Executor 的 query 方法,那么可以这样定义插件。

@Intercepts({
   
@Signature(
type = Executor.class,
method = "query",
args ={
   MappedStatement.class, Object.class, RowBounds.class, 
ResultHandler.class}
 )
})
public class ExamplePlugin implements Interceptor {
   
// 省略逻辑
}

除此之外,我们还需将插件配置到相关文件中。这样 MyBatis 在启动时可以加载插件,
并保存插件实例到相关对象(InterceptorChain,拦截器链)中。待准备工作做完后,MyBatis
处于就绪状态。我们在执行 SQL 时,需要先通过 DefaultSqlSessionFactory 创 建
SqlSession 。Executor 实例会在创建 SqlSession 的过程中被创建,Executor 实例创建完毕
后,MyBatis 会通过 JDK 动态代理为实例生成代理类。这样,插件逻辑即可在 Executor 相
关方法被调用前执行。以上就是 MyBatis 插件机制的基本原理。接下来,我们来看一下原
理背后对应的源码是怎样的。

1.1 植⼊插件逻辑

本节,我将以 Executor 为例,分析 MyBatis 是如何为 Executor 实例植入插件逻辑的。
Executor 实例是在开启 SqlSession 时被创建的,因此,下面我们从源头进行分析。先来看
一下 SqlSession 开启的过程。

// -☆- DefaultSqlSessionFactory
public SqlSession openSession() {
   
return openSessionFromDataSource(
configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, 
TransactionIsolationLevel level, boolean autoCommit) {
   
Transaction tx = null;
try {
   
// 省略部分逻辑
// 创建 Executor
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
 } 
catch (Exception e) {
   ...} 
finally {
   ...}
}

Executor 的创建过程封装在 Configuration 中,我们跟进去看看看。

// -☆- Configuration
public Executor newExecutor(Transaction transaction, 
ExecutorType executorType) {
   
executorType = executorType == null ?
defaultExecutorType : executorType;
executorType = executorType == null ?
ExecutorType.SIMPLE : executorType;
Executor executor;
// 根据 executorType 创建相应的 Executor 实例
if (ExecutorType.BATCH == executorType) {
   ...} 
else if (ExecutorType.REUSE 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值