IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> mybatis自定义插件开发 -> 正文阅读

[Java知识库]mybatis自定义插件开发

现在有这样一个需求:
需要自定义mybatis插件判断当前sql执行时间时候超过自定义的值,如果超时就打印相应的日志

  1. 插件自定义代码:
    github代码地址
@Intercepts(
        {
                @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
                @Signature(type = Executor.class, method = "queryCursor", args = {MappedStatement.class, Object.class, RowBounds.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        }
)
public class ConsumeTimeInterceptor implements Interceptor {

  public static Log log = LogFactory.getLog(ConsumeTimeInterceptor.class);

  long limitMilliSecond;

  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    long start = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    try {
      return invocation.proceed();
    } finally {
      try {
        long end = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        String methodName = invocation.getMethod().getName();
        long consumeTime = end - start;
        if (consumeTime > limitMilliSecond) {
          String logString;
          if ("update".equalsIgnoreCase(methodName)) {
            logString = "slow update consume milliSecond: ";
          } else {
            logString = "slow query consume milliSecond: ";
          }
          log.debug(logString + consumeTime);
        }
      } catch (Exception e) {
        log.error(e.getMessage());
      }
    }
  }

  @Override
  public void setProperties(Properties properties) {
    String limitMilliSecond = properties.getProperty("limitMilliSecond");
    if (limitMilliSecond != null) {
      this.limitMilliSecond = Long.parseLong(limitMilliSecond);
    }
  }
}

通过实现Interceptor接口,就可以实现一个自定义插件

  1. 在mybatis配置文件配置插件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <plugins>
        <plugin interceptor="io.github.mybatis.pal.ConsumeTimeInterceptor">
            <property name="limitMilliSecond" value="10"/>
        </plugin>
    </plugins>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="" value="" />
            </transactionManager>
            <dataSource type="UNPOOLED">
                <property name="driver" value="org.hsqldb.jdbcDriver" />
                <property name="url" value="jdbc:hsqldb:mem:basetest" />
                <property name="username" value="sa" />
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="io.github.mybatis.pal.Mapper" />
    </mappers>

</configuration>

  1. 我们看一下源码,看看插件是如何被设置生效的
    DefaultSqlSessionFactory中的方法
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      // 调用configuration的方法生成executor对象
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

configuration.newExecutor()方法如下:

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    // 生成executor执行interceptorChain的方法是所有插件生效
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

interceptorChain生成:在项目启动,configuration被初始化,读取配置文件生成

这里我们看到作用于executor的并不是单个插件,是一个插件链,意味着我们可以定义多个插件,也可能我们引入的其他插件也会作用于executor

比如:如果我们实际项目中引入了分页插件,此时分页插件也会在此处作用于executor,从而达到分页的目的

这里设置插件使用了责任链模式,返回的是一个动态代理类,使用了代理模式,具体可以看mybatis源码

如果想要自己实现一个插件,可以上github下载代码,依葫芦画瓢

下一篇文章,我们将学习如何在springboot项目中引入该插件,实现自动化配置插件,直接引入maven依赖包就可以使用,无需手动配置

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-03 12:54:30  更:2021-12-03 12:55:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:49:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码