MyBatis学习笔记9——MyBatis插件开发

本文详细介绍了MyBatis的插件机制,包括可拦截的接口和方法、拦截器接口与签名注解的使用,以及如何通过插件实现对执行器、参数处理、结果集处理和SQL语法构建的拦截。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mybatis 允许在映射语句执行过程中的某一点进行拦截调用。

默认情况下,Mybatis允许使用插件来拦截的接口和方法包括以下几个:

序号接口方法描述
1Executorupdate、query、flushStatements、commit、rollback、getTransaction、close、isClosed拦截执行器的方法
2ParameterHandlergetParameterObject、setParameters拦截参数的处理
3ResultSetHandlerhandleResultSets、handleCursorResultSets、handleOutputParameters拦截结果集的处理
4StatementHandlerprepare、parameterize、batch、update、query拦截Sql语法构建的处理

这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 的发行包中的源代码。 假设你想做的不仅仅是监控方法的调用,那么你应该很好的了解正在重写的方法的行为。 因为如果在试图修改或重写已有方法的行为的时候,你很可能在破坏 MyBatis 的核心模块。 这些都是底层的类和方法,所以使用插件的时候要特别当心。

拦截器接口介绍

MyBatis 插件可以用来实现拦截器接口 Interceptor (org.apache.ibatis.plugin.Interceptor ),在实现类中对拦截对象和方法进行处理。

先来看拦截器接口,了解该接口的每一个方法的作用和用法。Interceptor 接口代码如下:

public interface Interceptor { 
	Object intercept(Invocation invocation) throws Throwable; 
	Object plugin(Object target) ; 
	void setProperties(Properties properties); 
}

首先是 setProperties方法,这个方法用来传递插件的参数,可以通过参数来改变插件的行为。参数值传递原理如下:

mybatis-config.xml中,一般情况下,拦截器的配置如下:

<plugins> 
	<plugin interceptor="tk.mybatis.simple.plugin.XXXInterceptor">
		<property name="propl" value ="valuel"/>
		<property name="prop2" value ="value2"/>
	</plugin> 
</plugins>

在配置拦截器时,pluginInterceptor属性为拦截器实现类的全限定名称,如果需要参数,可以在plugin标签内通过property标签进行配置,配置后的参数在拦截器初始化时会通过setProperties方法传递给拦截器。在拦截器中可以很方便地通过Properties取得配置的参数值。

再看第二个方法plugin。这个方法的参数target就是拦截器要拦截的对象,该方法会在创建被拦截的接口实现类时被调用。该方法的实现很简单,只需要调用MyBatis提供的Pluginorg.apache.ibatis.plugin.Plugin)类的wrap静态方法就可以通过Java的动态代理拦截目标对象。这个接口方法通常的实现代码如下:

@Override
public Object plugin(Object target){
	return Plugin.wrap(target,this);
}

Plugin.wrap方法会自动判断拦截器的签名和被拦截对象的接口是否匹配,只有匹配的情况下才会使用动态代理拦截目标对象,因此在上面的实现方法中不必做额外的逻辑判断。

最后一个intercept方法是MyBatis运行时要执行的拦截方法。通过该方法的参数invocation可以得到很多有用的信息,该参数的常用方法如下:

@Override
public Object intercept(Invocation invocation) throws Throwable{
	Object target=invocation.getTarget();
	Method method=invocation.getMethod();
	Object[] args=invocation.getArgs();
	Object result=invocation.proceed();
	return result;
}

使用getTarget()方法可以获取当前被拦截的对象,使用getMethod()可以获取当前被拦截的方法,使用getArgs()方法可以返回被拦截方法中的参数。通过调用invocation.proceed();可以执行被拦截对象真正的方法,proceed()方法实际上执行了method.invoke(target,args)方法上面的代码中没有做任何特殊处理,直接返回了执行的结果。

当配置多个拦截器时,MyBatis会遍历所有拦截器,按顺序执行拦截器的plugin方法,被拦截的对象就会被层层代理。在执行拦截对象的方法时,会一层层地调用拦截器,拦截器通过invocation.proceed()调用下一层的方法,直到真正的方法被执行。方法执行的结果会从最里面开始向外一层层返回,所以如果存在按顺序配置的A、B、C三个签名相同的拦截器MyBatis会按照C>B>A>target.proceed()>A>B>C的顺序执行。如果A、B、C签名不同,就会按照**MyBatis拦截对象的逻辑**执行。
在这里插入图片描述

拦截器签名介绍

除了需要实现拦截器接口外,还需要给实现类配置以下的拦截器注解。

@Intercepts(org.apache.ibatis.plugin.Intercepts)和签名注解@Signature(org.apache.ibatis.plugin.Signature),这两个注解用来配置拦截器要拦截的接口的方法。

@Intercepts注解中的属性是一个@Signature(签名)数组,可以在同一个拦截器中同时拦截不同的接口和方法。

以拦截ResultSetHandler接口的handleResultSets方法为例,配置签名如下:

@Intercepts({
	@Signature(
  		type= ResultSetHandler.class,
  		method = "handleResultSets",
  		args = {Statement.class})
})
public class ResultSetInterceptor implements Interceptor

@Signature注解包含以下三个属性:

  • type设置拦截的接口,可选值是前面提到的4个接口
  • method设置拦截接口中的方法名,可选值是前面4个接口对应的方法,需要和接口匹配
  • args设置拦截方法的参数类型数组,通过方法名和参数类型可以确定唯一一个方法。

由于MyBatis代码具体实现的原因,可以被拦截的4个接口中的方法并不是都可以被拦截的。下面将针对这4种接口,讲可以被拦截的方法以及方法被调用的位置和对应的拦截器签名依次列举出来。

Executor接口

ExecutorMybatis的内部执行器。它负责调用StatementHandler操作数据库,并把结果集通过 ResultSetHandler进行自动映射。

另外,它还处理了二级缓存的操作。从这里可以看出,我们也是可以通过插件来实现自定义的二级缓存的。

Executor接口包含以下几个方法:

update

int update(MappedStatement ms, Object parameter) throws SQLException;

该方法会在所有的INSERTUPDATEDELETE执行时被调用,因此如果想要拦截这3类操作,可以拦截该方法。接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "update",
	args = {MappedStatement.class, Object.class})

query

<E> List<E> query(
		MappedStatement ms, 
		Object parameter, 
		RowBounds rowBounds, 
		ResultHandler resultHandler) throws SQLException;

该方法会在所有SELECT查询方法执行时被调用。通过这个接口参数可以获取很多有用的信息,因此这是最常被拦截的一个方法。使用该方法需要注意的是,虽然接口中还有一个参数更多的同名接口,但由于MyBatis的设计原因,这个参数多的接口不能被拦截。接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "query",
	args = {MappedStatement.class, Object.class,
			RowBounds.class, ResultHandler.class})

queryCursor

<E> Cursor<E> queryCursor(
		MappedStatement ms, 
		Object parameter, 
		RowBounds rowBounds) throws SQLException;

该方法只有在查询的返回值类型为Cursor被调用。接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "queryCursor",
	args = {MappedStatement.class, Object.class,
			RowBounds.class})

flushStatements

List<BatchResult> flushStatements() throws SQLException;

该方法只在通过SqlSession方法调用flushStatements方法或执行的接口方法中带有@Flush注解时才被调用,接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "flushStatements",
	args = {})

commit

void commit(boolean required) throws SQLException

该方法只在通过SqlSession方法调用commit方法时才被调用,接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "commit",
	args = {boolean.class})

rollback

void rollback(boolean required) throws SQLException;

该方法只在通过SqlSession方法调用rollback方法时才被调用,接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "rollback",
	args = {boolean.class})

getTransaction

Transaction getTransaction();

该方法只在通过SqlSession方法获取数据库连接时才被调用,接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "getTransaction",
	args = {})

close

void close(boolean forceRollback);

该方法只在延迟加载获取新的Executor才会被执行,接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "close",
	args = {boolean.class})

isClosed

boolean isClosed();

该方法只在延迟加载执行查询方法前被执行,接口方法对应的签名如下:

@Signature(
	type= Executor.class,
	method = "isClosed",
	args = {})

ParameterHandler接口

ParameterHandlerMybatis实现Sql入参设置的对象。

这里,使用插件可以改变我们Sql的参数默认设置。

ParameterHandler接口包含以下两个方法:

getParameterObject

Object getParameterObject();

该方法只在执行存储过程处理出参的时候被调用,接口方法对应的签名如下:

@Signature(
	type= ParameterHandler.class,
	method = "getParameterObject",
	args = {})

setParameters

void setParameters(PreparedStatement ps) throws SQLException;

该方法在所有数据库方法设置SQL参数时被调用,接口方法对应的签名如下:

@Signature(
	type= ParameterHandler.class,
	method = "setParameters",
	args = {PreparedStatement.class})

ResultSetHandler接口

ResultSetHandlerMybatisResultSet集合映射成POJO的接口对象。

我们可以定义插件对Mybatis的结果集自动映射进行修改。

ResultSetHandler接口包含以下三个方法:

handleResultSets

<E> List<E> handleResultSets(Statement stmt) throws SQLException;

该方法会在除存储过程及返回值类型为Cursor<T>org.apache.ibatis.cursor.Cursor<T>)以外的查询方法中被调用,接口方法对应的签名如下:

@Signature(
	type= ResultSetHandler.class,
	method = "handleResultSets",
	args = {Statement.class})

handleCursorResultSets

<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

该方法是在3.4.0版本中新增加的,只会在返回值类型为Cursor<T> 的查询方法中被调用,接口方法对应的签名如下:

@Signature(
	type= ResultSetHandler.class,
	method = "handleCursorResultSets",
	args = {Statement.class})

handleOutputParameters

void handleOutputParameters(CallableStatement cs) throws SQLException;

该方法只在使用存储过程处理出参时被调用,接口方法对应的签名如下:

@Signature(
	type= ResultSetHandler.class,
	method = "handleOutputParameters",
	args = {CallableStatement.class})

ResultSetHandler接口的第一个方法对于拦截处理MyBatis的查询结果非常有用,并且由于这个接口被调用的位置在处理二级缓存之前,因此通过这种方式处理的结果可以执行二级缓存。

StatementHandler接口

StatementHandlerMybatis直接和数据库执行sql脚本的对象。

另外它也实现了Mybatis的一级缓存。这里,我们可以使用插件来实现对一级缓存的操作(禁用等等)。

StatementHandler接口包含以下几个方法:

prepare

Statement prepare(
		Connection connection, 
		Integer transactionTimeout) throws SQLException;

该方法会在数据库执行前被调用,优先于当前接口中的其他方法而被执行,接口方法对应的签名如下:

@Signature(
	type= StatementHandler.class,
	method = "prepare",
	args = {Collection.class, Integer.class})

parameterize

 void parameterize(Statement statement) throws SQLException;

该方法prepare方法之后执行,用于处理参数信息,接口方法对应的签名如下:

@Signature(
	type= StatementHandler.class,
	method = "parameterize",
	args = {Statement.class})

batch

int batch(Statement statement)  throws SQLException;

全局设置配置defaultExecutorType="BATCH"时,执行数据操纵才会调用该方法,接口方法对应的签名如下:

@Signature(
	type= StatementHandler.class,
	method = "batch",
	args = {Statement.class})

query

 <E> List<E> query(
 		Statement statement, 
 		ResultHandler resultHandler) throws SQLException;

执行SELECT方法时调用,接口方法对应的签名如下:

@Signature(
	type= StatementHandler.class,
	method = "query",
	args = {Statement.class, ResultHandler.class})

queryCursor

<E> Cursor<E> queryCursor(Statement statement) throws SQLException;

该方法是在3.4.0版本中新增加的,只会在返回值类型为Cursor<T> 的查询中被调用,接口方法对应的签名如下:

@Signature(
	type= StatementHandler.class,
	method = "queryCursor",
	args = {Statement.class})
<think>好的,用户需要寻找与MyBatis插件相关的资料或教程,特别是开发和使用方面的内容。现在需要根据提供的引用内容来整理回答。首先,我需要回顾用户提供的四个引用,这些引用都提到了不同的MyBatis插件,比如MyBatis Generator、MyBatisX等,以及它们的安装和使用方法。 首先,确定用户的需求是寻找教程和资料,所以回答需要涵盖插件的介绍、安装步骤、核心功能以及使用步骤。然后,根据每个引用的内容提取关键点。例如,引用1提到MyBatis Generator的启动文件和目录结构,引用2和3详细说明了MyBatisX插件的安装步骤和功能,引用4则补充了MyBatisX的作用。 接下来,需要将这些信息整合成一个结构清晰的回答。可能需要分为几个部分:插件简介、安装教程、核心功能、使用步骤以及相关资源推荐。同时,要确保引用标注正确,比如在提到每个插件的功能时,对应到正确的引用来源。 另外,用户可能对如何开发自己的插件感兴趣,但提供的引用中没有详细说明开发过程,所以可能需要建议参考官方文档或社区资源。同时,生成的相关问题要围绕MyBatis插件的使用、对比、选择以及开发,确保问题贴合用户的潜在需求。 需要检查每个步骤是否符合用户的要求,比如使用正确的中文表达,LaTeX格式是否正确应用(虽然当前问题可能不涉及数学公式,但如果有的话需要处理),以及是否自然添加引用标识。最后,确保回答真实可靠,基于提供的引用内容,不添加未提及的信息。</think>以下是与MyBatis插件相关的教程和核心信息整理: ### 一、MyBatis插件分类与用途 1. **MyBatis Generator插件** 用于自动生成MyBatis的Mapper接口、XML映射文件和实体类。其核心启动文件为`ExampleTargetPlugin.java`,位于`src/main/java/com/itfsw/mybatis/generator/plugins/`目录下[^1]。 2. **MyBatisX插件(IDEA集成)** 提供代码生成、智能补全、语法高亮、数据库操作等功能,支持MyBatisMyBatis-Plus开发[^2][^4]。 --- ### 二、插件安装教程 #### MyBatisX安装步骤(IntelliJ IDEA) 1. 打开IDEA,进入`File > Settings > Plugins` 2. 在插件市场搜索"MyBatisX" 3. 点击`Install`安装,重启IDEA生效[^2][^3] #### MyBatis Generator配置 需在项目的`pom.xml`中添加MyBatis-Plus依赖(以Spring Boot项目为例): ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>最新版本号</version> </dependency> ``` --- ### 三、核心功能对比 | 插件名称 | 核心能力 | 优势场景 | |------------------|--------------------------------------------------------------------------|------------------------| | MyBatis Generator| 自动生成基础CRUD代码 | 快速搭建项目框架 | | MyBatisX | 代码生成、SQL跳转、数据库管理、文档生成 | 开发效率提升与代码维护 | --- ### 四、MyBatisX使用步骤 1. **代码生成** - 右键项目中的表,选择`MyBatisX-Generator` - 配置生成路径和包名,自动生成Mapper/Service/Entity代码 2. **数据库操作** - 在IDEA内直接执行SQL语句 - 支持可视化数据表浏览与编辑 3. **导航与校验** - 通过`XML <-> Java`双向跳转快速定位代码 - 实时语法错误检查 --- ### 五、相关资源推荐 1. **官方文档** - [MyBatis Generator官方指南](https://mybatis.org/generator/) - [MyBatisX插件GitHub仓库](https://github.com/baomidou/mybatis-plus) 2. **社区教程** - MyBatisX插件详细使用案例(含动图演示)[^2] - 插件开发进阶:自定义模板方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值