Skip to content

Latest commit

 

History

History
86 lines (72 loc) · 3.56 KB

核心组件.md

File metadata and controls

86 lines (72 loc) · 3.56 KB

image

对象 解释
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

该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;
	}
}