看完sql生成过程,咱们再来看看mapper接口的实例化。众所周知,接口是没法实例化的,那Mybatis到底实例出来的是什么东西呢?java
mapper的实例化经过SqlSession获取的,所以咱们先来看看SqlSession的建立过程:web
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
能够看到Executor也在这里实例化了,还记得Executor是真正发起数据库操做的执行器,而且Executor有多个实现类,这里到底使用的是哪一个实现类呢sql
public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (cacheEnabled) { executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
发现Executor一共四个实现类:BatchExecutor、ReuseExecutor、SimpleExecutor、CachingExecutor,其用途看名字基本能够猜出来:数据库
另外,咱们还留意到interceptorChain.pluginAll(executor);,看起来跟web的filter链十分类似,其实内部的确是一条责任链:缓存
public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; }
经过查看其调用链,咱们发现不只executor调用了:session
这是Mybatis的一种扩展机制,经过拦截器添加自定义操做,须要实现各自的接口并实现到全局配置中。app
注意:Inteceptor是使用JDK的动态代理来实现的,因此它只能对接口进行拦截分布式
executor建立完成后,将其与Configuration一块儿传入DefaultSqlSession,至此SqlSession建立完成。接下来利用SqlSession.getMapper实例化mapper,其实是经过mapperRegistry进行。还记得mapperRegistry一开始在解析mapper时建立了Mapper代理工厂类MapperProxyFactory,这个工厂类一样是使用了JDK的动态代理来建立代理类MapperProxy:fetch
protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }
当调用mapper方法时,就会进入其实现了InvocationHandler的invoke方法,以后的流程在从源码看世界:Mybatis一次数据库操做过程已说明,这里再也不叙述。this