看完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