读取配置,加载配置后,有了数据源后,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的地方在这