1. 时序图
2. 通过 getMapper 获取实现类
@Test
public void test ( ) throws IOException {
String resource = "mybatis-config.xml" ;
InputStream inputStream = Resources. getResourceAsStream ( resource) ;
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ( ) . build ( inputStream) ;
SqlSession openSession = sqlSessionFactory. openSession ( ) ;
try {
EmployeeMapper mapper = openSession. getMapper ( EmployeeMapper. class ) ;
Employee employee = mapper. getEmpById ( 1 ) ;
System. out. println ( employee) ;
} finally {
openSession. close ( ) ;
}
}
3. 获取 SqlSession
3.1 DefaultSqlSessionFactory#openSession
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
@Override
public SqlSession openSession ( ) {
return openSessionFromDataSource ( configuration. getDefaultExecutorType ( ) , null, false ) ;
}
3.2 Configuration#getDefaultExecutorType
org.apache.ibatis.session.Configuration
public ExecutorType getDefaultExecutorType ( ) {
return defaultExecutorType;
}
3.3 DefaultSqlSessionFactory#openSessionFromDataSource
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
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) ;
throw ExceptionFactory. wrapException ( "Error opening session. Cause: " + e, e) ;
} finally {
ErrorContext. instance ( ) . reset ( ) ;
}
}
3.4 Configuration#newExecutor
org.apache.ibatis.session.Configuration
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;
}
3.5 InterceptorChain#pluginAll
org.apache.ibatis.plugin.InterceptorChain
public Object pluginAll ( Object target) {
for ( Interceptor interceptor : interceptors) {
target = interceptor. plugin ( target) ;
}
return target;
}
4. 调用 getMapper 获取实现类
4.1 DefaultSqlSession#getMapper
org.apache.ibatis.session.defaults.DefaultSqlSession
@Override
public < T> T getMapper ( Class< T> type) {
return configuration. < T> getMapper ( type, this ) ;
}
4.2 Configuration#getMapper
org.apache.ibatis.session.Configuration
public < T> T getMapper ( Class< T> type, SqlSession sqlSession) {
return mapperRegistry. getMapper ( type, sqlSession) ;
}
4.3 MapperRegistry#getMapper
org.apache.ibatis.binding.MapperRegistry
public < T> T getMapper ( Class< T> type, SqlSession sqlSession) {
final MapperProxyFactory< T> mapperProxyFactory = ( MapperProxyFactory< T> ) knownMappers. get ( type) ;
if ( mapperProxyFactory == null) {
throw new BindingException ( "Type " + type + " is not known to the MapperRegistry." ) ;
}
try {
return mapperProxyFactory. newInstance ( sqlSession) ;
} catch ( Exception e) {
throw new BindingException ( "Error getting mapper instance. Cause: " + e, e) ;
}
}
4.4 MapperProxyFactory#newInstance
org.apache.ibatis.binding.MapperProxyFactory
public T newInstance ( SqlSession sqlSession) {
final MapperProxy< T> mapperProxy = new MapperProxy < T> ( sqlSession, mapperInterface, methodCache) ;
return newInstance ( mapperProxy) ;
}
4.5 MapperProxyFactory#newInstance
org.apache.ibatis.binding.MapperProxyFactory
protected T newInstance ( MapperProxy< T> mapperProxy) {
return ( T) Proxy. newProxyInstance ( mapperInterface. getClassLoader ( ) , new Class [ ] { mapperInterface } , mapperProxy) ;
}
4.6 Proxy#newProxyInstance
public static Object newProxyInstance ( ClassLoader loader,
Class< ? > [ ] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects. requireNonNull ( h) ;
final Class< ? > [ ] intfs = interfaces. clone ( ) ;
final SecurityManager sm = System. getSecurityManager ( ) ;
if ( sm != null) {
checkProxyAccess ( Reflection. getCallerClass ( ) , loader, intfs) ;
}
Class< ? > cl = getProxyClass0 ( loader, intfs) ;
. . .
}
mapperProxy 会为 getEmpById() 方法生成代理方法,所有的代理方法如下
0 = { Method@1751 } "public final boolean com.sun.proxy.$Proxy4.equals(java.lang.Object)"
1 = { Method@1752 } "public final java.lang.String com.sun.proxy.$Proxy4.toString()"
2 = { Method@1753 } "public final int com.sun.proxy.$Proxy4.hashCode()"
3 = { Method@1754 } "public final pers.mangseng.study.mybatis.pojo.Employee com.sun.proxy.$Proxy4.getEmpById(java.lang.Integer)"
4 = { Method@1755 } "public static boolean java.lang.reflect.Proxy.isProxyClass(java.lang.Class)"
5 = { Method@1756 } "public static java.lang.Object java.lang.reflect.Proxy.newProxyInstance(java.lang.ClassLoader,java.lang.Class[],java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException"
6 = { Method@1757 } "public static java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.getInvocationHandler(java.lang.Object) throws java.lang.IllegalArgumentException"
7 = { Method@1758 } "public static java.lang.Class java.lang.reflect.Proxy.getProxyClass(java.lang.ClassLoader,java.lang.Class[]) throws java.lang.IllegalArgumentException"
8 = { Method@1759 } "public final void java.lang.Object.wait() throws java.lang.InterruptedException"
9 = { Method@1760 } "public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException"
10 = { Method@1761 } "public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException"
11 = { Method@1762 } "public final native java.lang.Class java.lang.Object.getClass()"
12 = { Method@1763 } "public final native void java.lang.Object.notify()"
13 = { Method@1764 } "public final native void java.lang.Object.notifyAll()"