对象 | 解释 |
---|---|
SqlSessionFactoryBuilder | 负责创建SqlSessionFactory,可以从xml配置文件或者一个定义好的Confiugration对象创建SqlSessionFactory |
SqlSessionFactory | 负责创建SqlSession,提供了一系列openSession方法用于创建SqlSession |
SqlSession | 表示sql会话,应用和mybatis的桥梁,它在接收到调用请求后,会调用mybatis核心处理层来完成具体操作 |
Executor | 执行器,负责生成BoundSql对象表示动态sql语句,缓存维护 |
StatementHandler | 负责调用jdbc Statement进行数据库操作,操作结果返回 |
ParameterHandler | 负责将应用传递的参数转换成jdbc Statement所需要的参数 |
TypeHandler | 负责java数据类型和jdbc数据类型的转换 |
Statement | jdbc Statement,用于执行sql语句 |
ResultSet | 保存sql执行返回结果 |
ResultSetHandler | 负责结果集映射,将ResultSet映射为应用需要的对象 |
mybatis拦截器允许我们在mybatis核心方法执行前后做一些拦截处理,比如sql替换,加密等。mybatis支持对Executor、StatementHandler、PameterHandler和ResultSetHandler 接口进行拦截,核心是实现Interceptor接口。该接口定义如下:
public interface Interceptor {
//拦截方法,Invocation包装了要执行的方法,通过invocation.proceed即可调用方法
Object intercept(Invocation invocation) throws Throwable;
//生成代理对象
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
//可以设置一些属性
default void setProperties(Properties properties) {
// NOP
}
}
核心就是intercept方法,通过Invocation对象我们可以拿到要执行的方法信息,sql和参数等。
另外可以通过@Intercepts注解来指定要拦截的方法,比如只需要拦截Executor的query方法
该demo用于拦截Exector的执行方法,记录慢sql。实际可以根据需要在intercept方法内实现。
@Component
@Slf4j
//指定要拦截的方法,我们写的select都会走Executor的query方法,insert/update/delete会走Executor的update方法
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class ExecutorInterceptor implements Interceptor {
private final static int SLOW_SQL_TIME = 500;
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
//如果是Executor才进行代理,避免非目标对象被代理
return Plugin.wrap(target, this);
}
return target;
}
@Override
public void setProperties(Properties properties) {
//这里可以设置一些属性值,在intercept时使用
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
//获取参数
Object[] args = invocation.getArgs();
//MappedStatement封装了mapper接口的方法
MappedStatement mappedStatement = (MappedStatement) args[0];
Long before = System.currentTimeMillis();
Object result = invocation.proceed();
Long after = System.currentTimeMillis();
if (after - before > SLOW_SQL_TIME) {
log.warn("slow sql:{}", mappedStatement.getBoundSql(args).getSql());
}
return result;
}
}