✅Mybatis插件的运行原理?

✅Mybatis插件的运行原理?

典型回答

Mybatis插件的运行原理主要涉及3个关键接口:Interceptor、Invocation和Plugin。

  1. Interceptor:拦截器接口,定义了Mybatis插件的基本功能,包括插件的初始化、插件的拦截方法以及插件的销毁方法。
  2. Invocation:调用接口,表示Mybatis在执行SQL语句时的状态,包括SQL语句、参数、返回值等信息。
  3. Plugin:插件接口,Mybatis框架在执行SQL语句时,会将所有注册的插件封装成Plugin对象,通过Plugin对象实现对SQL语句的拦截和修改。

插件的运行流程如下:

  1. 首先,当Mybatis框架运行时,会将所有实现了Interceptor接口的插件进行初始化。
  2. 初始化后,Mybatis框架会将所有插件和原始的Executor对象封装成一个InvocationChain对象。(这里使用的是责任链模式)
  3. 每次执行SQL语句时,Mybatis框架都会通过InvocationChain对象依次调用所有插件的intercept方法,实现对SQL语句的拦截和修改。
  4. 最后,Mybatis框架会将修改后的SQL语句交给原始的Executor对象执行,并将执行结果返回给调用方。

通过这种方式,Mybatis插件可以对SQL语句进行拦截和修改,实现各种功能,例如查询缓存、分页、分库分表等。

知识扩展

常见的Mybatis插件有哪些?

常见的插件如PageHelper,用于分页使用

✅PageHelper分页的原理是什么?

自己有写过Mybatis插件吗?

笔者之前在做应用迁移的时候,通过Mybatis插件机制完成过一个功能,可以通过注册中心一键切换应用的数据源,伪代码如下所示:

@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}),
    @Signature(method = "query", type = Executor.class,
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class,
            BoundSql.class}), @Signature(method = "query", type = Executor.class,
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MultipleDataSourceInterceptor implements Interceptor {
    private static String dataSourceKey = null;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 每次请求,都去设置最新的数据源(至于数据源如何更换,则就是另一个话题了)
        if (dataSourceKey != null) {
            DataSourceHolder.setDataSource(dataSourceKey);
        }
        return invocation.proceed();
    }

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

    @Override
    public void setProperties(Properties properties) {
        //do nothing
    }

    public void registerCallback(String data) {
        dataSourceKey = data;
    }
}