插件源码进一步分析与pageHelper分页插件介绍
知识回顾
上一篇 自定义MyBatis插件。我们实习了自定义插件,接下来我们先分析一下他的执行逻辑。
Plugin 实现了 InvocationHandler 接口,因此它的 invoke 方法会拦截所有的方法调用。invoke 方法会 对所拦截的方法进行检测,以决定是否执行插件逻辑。
我们看看 org.apache.ibatis.plugin.Plugin.java
public class Plugin implements InvocationHandler {
private final Object target;
private final Interceptor interceptor;
private final Map<Class<?>, Set<Method>> signatureMap;
private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
this.target = target;
this.interceptor = interceptor;
this.signatureMap = signatureMap;
}
public static Object wrap(Object target, Interceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
return interfaces.length > 0 ? Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)) : target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Set<Method> methods = (Set)this.signatureMap.get(method.getDeclaringClass());
return methods != null && methods.contains(method) ? this.interceptor.intercept(new Invocation(this.target, method, args)) : method.invoke(this.target, args);
} catch (Exception var5) {
Exception e = var5;
throw ExceptionUtil.unwrapThrowable(e);
}
}
...
}
首先,invoke 方法会检测被拦截方法是否配置在插件的 @Signature 注解 中,若是,则执行插件逻辑,否则执行被拦截方法。插件逻辑封装在 org.apache.ibatis.plugin.Interceptor 的 intercept 方法中,该方法的参数类型为 Invocation ,主要用于存储目标类,方法以及方法参数列表。
public interface Interceptor {
Object intercept(Invocation var1) throws Throwable;
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
default void setProperties(Properties properties) {
}
}
分页插件分享
MyBatis 可以使用第三方的插件来对功能进行扩展,分⻚助手 PageHelper 就是其中一个非常优秀的插件。它将分⻚的复杂操作进行封装,使用简单的方式即可获得带分⻚的数据。
开发步骤:
-
导入通用 PageHelper 的坐标
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.1</version> </dependency> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>4.0</version> </dependency>
-
在 mybatis 核心配置文件中配置 PageHelper 插件并测试分⻚数据获取
配置文件
<!--注意:分⻚助手的插件 配置在通用馆mapper之前--> <plugin interceptor="com.github.pagehelper.PageHelper"> <!—指定方言 —> <property name="dialect" value="mysql"/> </plugin>
测试:
@Test
public void testPageHelper() {
//设置分⻚参数
// PageHelper.startPage(1, 2);
List<User> select = userMapper.findAll();
for (User user : select) {
System.out.println(user);
}
}
没有分页的结果
Total: 4
User{id=1, username='lisi'}
User{id=2, username='tom'}
User{id=8, username='测试2'}
User{id=9, username='测试3'}
分页的结果
Total: 2
User{id=1, username='lisi'}
User{id=2, username='tom'}
分页实例代码