美文网首页MyBatis学习(完)
MyBatis快速入门(09)全局配置--插件

MyBatis快速入门(09)全局配置--插件

作者: 郭艺宾 | 来源:发表于2019-07-23 22:20 被阅读8次

    在SQL语句方法执行的过程中,MyBatis 允许你编写插件(plugin)在执行过程中的某一点进行拦截调用,执行自己的定制化业务。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

    Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)

    ParameterHandler (getParameterObject, setParameters)

    ResultSetHandler (handleResultSets, handleOutputParameters)

    StatementHandler (prepare, parameterize, batch, update, query)

    这些类中方法的详情可以通过查看每个方法的签名来发现,而且它们的源代码存在于MyBatis发行包中。你应该理解你所覆盖方法的行为,假设你所做的要比监视调用要多。如果你尝试修改或覆盖一个给定的方法,你可能会打破MyBatis的核心。这是低层次的类和方法,要谨慎使用插件。

    上面的话简单的说就是我们可以编写mybatis插件,在执行过程中插入自己的业务逻辑,其实就是一个拦截器。通过mybatis的机制,自定义插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可:

    写好插件类后,需要把类配置到mybatis配置文件中:

    上面的插件将会拦截在 Executor 实例中所有的 “select” 方法调用, 这里的 Executor 是负责执行低层映射语句的内部对象。

    提示: 覆盖配置类

    除了用插件来修改 MyBatis 核心行为之外,还可以通过完全覆盖配置类来达到目的。只需继承后覆盖其中的每个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会严重影响 MyBatis 的行为,务请慎之又慎。

    实战:通过编写插件打印出SQL语句

    下面通过代码来演示一下如何使用MyBatis的插件,要演示的场景是:打印每条真正执行的SQL语句。这是一个非常有用的需求,MyBatis本身的日志可以记录SQL,但是没办法统计SQL执行的时间。

    接下来定义插件,首先是类上面的注解,

    注解@Intercepts与@Signature,这两个注解是必须的,因为Plugin的wrap方法会取这两个注解里面参数。@Intercepts中可以定义多个@Signature,一个@Signature表示符合如下条件的方法才会被拦截:

    接口必须是type定义的类型

    方法名必须和method一致

    方法形参的Class类型必须和args定义Class类型顺序一致

    接着的一个问题是:有四个接口可以拦截,为什么使用StatementHandler去拦截?根据名字来看ParameterHandler和ResultSetHandler,前者处理参数,后者处理结果是不可能使用的,剩下的就是Executor和StatementHandler了。拦截StatementHandler的原因是而不是用Executor的原因是:

    Executor的update与query方法可能用到MyBatis的一二级缓存从而导致统计的并不是真正的SQL执行时间(关于缓存,后面会讲到)

    StatementHandler的update与query方法无论如何都会统计到PreparedStatement的execute方法执行时间,尽管也有一定误差(误差主要来自会将处理结果的时间也算上),但是相差不大

    接着看一下实现接口需要处理的三个方法。首先是最简单的setProperties方法,如果需要从配置中传入参数到插件,可以在plugin标签下面继续写property标签,本插件不需要传入参数,因此setProperties方法内容为空即可。

    接着讲一下plugin方法,这里是为目标接口生成代理,不需要也没必要自己去写生成代理的方法,MyBatis的Plugin类已经为我们提供了wrap方法(当然如果自己有自己的逻辑也可以在Plugin.wrap方法前后加入,但是最终一定要使用Plugin.wrap方法生成代理),看一下该方法的实现:

    因为这里的target一定是一个接口,因此可以放心使用JDK本身提供的Proxy类,这里相当于就是如果该接口满足方法签名那么就为之生成一个代理。插件前半部分的写法都很简单,现在的内容如下:

    最后就是intercept方法了,这里就是拦截器的核心代码了。

    唯一要注意的一点就是无论如何最终一定要返回invocation.proceed(),保证拦截器的层层调用。我们来执行一下看看效果:

    代码地址:https://gitee.com/blueses/mybatis-demo 03

        

            

        

        

        

    我们的交流基地,“JAVA互联网技术交流:789650498”欢迎小伙伴们一起来交流:

    相关文章

      网友评论

        本文标题:MyBatis快速入门(09)全局配置--插件

        本文链接:https://www.haomeiwen.com/subject/liholctx.html