mybatis深度解析4--拿到sql

本文介绍了mybatis中的插件机制,重点讲解了如何在插件中访问SQL,以及Executor的工作原理,特别是CachingExecutor如何处理动态SQL。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读取配置,加载配置后,有了数据源后,myBatis如何拿到sql的呢?

讲这个之前,要先明白两个东西:mybatis的插件plugin和执行器Executor

插件plugin
写个简单的插件样子:
@Intercepts({// 这里可以定义多个拦截点
        @Signature(
                type = Executor.class, // 拦截的接口名称
                method = "query", // 接口内方法名
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} // 拦截方法的入参类型
        )
})
public class ExamplePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 自定义增强逻辑
        System.out.println("自定义增强逻辑");
        System.out.println("args: " + Arrays.toString(invocation.getArgs()));
        System.out.println("target:" + String.valueOf(invocation.getTarget()));
        System.out.println("method:" + invocation.getMethod().getName());
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];

        // SqlSource sqlSource = mappedStatement.getSqlSource();
        // Class<?> aClass = ReflectUtil.getClass(sqlSource);
        // Field field = ReflectUtil.getField(aClass, "sqlSource");
        // field.setAccessible(true);
        // StaticSqlSource staticSqlSource =  (StaticSqlSource) field.get(sqlSource);
        // Object sql = ReflectUtil.getFieldValue(staticSqlSource, "sql");

        // System.out.println("sql: " + sql);
        return invocation.proceed(); // 执行原有方法
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    /**
     * 传入的参数
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
        System.out.println(properties);
    }

配置文件如下,springboot只要把插件类注册成bean,mybatis会自动加载,道理和数据源切换成druid是一样的,后面看spring源码的时候可以看看究竟怎么接入的

    <plugins>
        <plugin interceptor="com.local.mybatis.plugin.ExamplePlugin">
            <property name="name" value="value"/>
        </plugin>
    </plugins>
那它在哪里使用了插件呢

还是要回到Configuration对象

这五个对象底层都是map,分别用来存放:
1、我们编写Mapper接口和其代理类
2、我们自定义的插件
3、java和数据库类型映射处理
4、系统默认和我们自己写的别名
5、脚本语言解析对象

然后我们看看这个执行器是怎么创建出来的
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

如此看来,如果有自定义插件,执行器创建的都是代理对象,自然也会执行我们写的增强逻辑

再来看执行器Executor

通常我们默认使用的是CachingExecutor,因为一级缓存是默认开启的
我们知道Mapper接口的对象是mybatis基于java的动态代理创建出来的,那么这个对象到底怎么用了执行器?
1、我们用这个方法获取Mapper的代理对象
在这里插入图片描述

2、之前说了这个Registry是用来存放Mapper接口和代理对象的,它可以拿到代理对象的创建工厂
在这里插入图片描述
在这里插入图片描述

3、代理对象的方法中写了,
在这里插入图片描述

4、这个execute执行的就是Configuration中执行器的方法,而执行器可能是代理的或者默认的
在这里插入图片描述

5、至于用了那种执行器,要看我们有没有修改执行器的类型,
在这里插入图片描述

6、如果开启了缓存,那么一定会用Caching这个执行器
在这里插入图片描述

搞清楚执行器,就看看执行器到底怎么搞到sql的

我们以查询的动态sql为例,CachingExecutor实际执行sql的地方在这
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值