mybatis插件原理

1,662 阅读2分钟

mybatis插件原理

mybatis的插件实现主要是基于JDK动态代理来实现的。下面来根据源码执行流程来分析代理执行的逻辑

大致分为如下几个流程:

插件定义和配置

可以通过xml的方式或者JavConfig两种方式定义插件,例如:

在 MyBatis 配置 xml 中配置拦截器插件

<plugins>
 <!-- com.github.pagehelper为PageHelper类所在包名 -->
 <plugin interceptor="com.github.pagehelper.PageInterceptor">
     <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
     <property name="param1" value="value1"/>
 </plugin>
</plugins>

在 Spring 配置文件中配置拦截器插件

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <!-- 注意其他配置 -->
  <property name="plugins">
    <array>
      <bean class="com.github.pagehelper.PageInterceptor">
        <property name="properties">
          <!--使用下面的方式配置参数,一行配置一个 -->
          <value>
            params=value1
          </value>
        </property>
      </bean>
    </array>
  </property>
</bean>

插件加载

插件的配置信息是封装在Configuration对象中,这个对象的封装完成在SqlSessionFactoryBeanafterPropertiesSet方法中,熟悉spring生命周期的同学应该对这个方法比较熟悉,该方法会在bean实例化的时候会被调用。

具体来讲就是在buildSqlSessionFactory方法中,插件载入后就存放在Configuration中。

protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
.....

if (!isEmpty(this.plugins)) {
      Stream.of(this.plugins).forEach(plugin -> {
        targetConfiguration.addInterceptor(plugin);
        LOGGER.debug(() -> "Registered plugin: '" + plugin + "'");
      });
    }
......

}

生成代理对象

mybatis支持对四个重要对象进行插件扩展,分别是:

ParameterHandler ResultSetHandler StatementHandler

Executor

每个对象的绑定时机不尽一致。其中Executor 的绑定发生在客户端open一个session的时候,详细的执行调时序图如下见下图

插件代理实例化过程
) 从这里面可以看到,我们的执行器实际上是从Plugin中生成的代理对象。

插件调用和执行

当我们使用执行器执行数据库操作的时候,实际上会执行上面生成的代理对象invoke方法中的interceptor.intercept命令,也就是会执行我们自定义的Interceptor中的intercept()方法,在这里面我们可以做一些SQL组装、监控之类的事情;

插件执行流程