问题:项目中一般会声明Mapper接口,接口包含了访问db的相关方法,然后在对应的xml文件中配置和接口暴露方法相对应的sql,我们没有实现Mapper接口,为什么可以通过如下代码进行访问数据库的操作?
public void testGetUserByUserName() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("config/mybatis/mybatis-config.xml");
SqlSession sqlSession = new SqlSessionFactoryBuilder().build(inputStream).openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.getUserByUserName("test"));
}
上一章节介绍了mybatis标签解析的内容,构建了SqlSessionFactory,本章节分析mapper的创建过程。首先通过sqlSessionFactory.openSession()获取session:
DefaultSqlSessionFactory:
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
// 获取环境对象
final Environment environment = configuration.getEnvironment();
// 默认的TransactionFactory是ManagedTransactionFactory
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 默认的tranction对象(jdbc connection的包装对象,管理connection的creation、preparation、commit/rollback、close等)是ManagedTransaction。
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 构建executor对象
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();
}
}
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(对select操作无效)
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
// 重用statement的执行器(在内存中缓存生成的statement对象,提高效率)
executor = new ReuseExecutor(this, transaction);
} else {
// 普通执行器(^_^)
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
// 支持缓存的executor(包装上述executor),配置cacheEnabled属性时生效
executor = new CachingExecutor(executor);
}
// 如果配置了插件(实现Interceptor接口),用插件封装executor
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
InterceptorChain:
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
Interceptor:
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public static Object wrap(Object target, Interceptor interceptor) {
// 获取interceptor配置的classType,以及拦截方法的映射
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
Class<?> type = target.getClass();
// 获取type所有在signatureMap中的interface
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if (interfaces.length > 0) {
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap)); // jdk动态代理生成代理。
}
return target;
}
Plugin: 实现了InvocationHandler接口
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 判断interceptor是否配置了当前class、method的插件。
Set<Method> methods = signatureMap.get(method.getDeclaringClass());
if (methods != null && methods.contains(method)) {
return interceptor.intercept(new Invocation(target, method, args)); // 调用插件方法
}
return method.invoke(target, args); // 直接通过反射执行目标method
} catch (Exception e) {
throw ExceptionUtil.unwrapThrowable(e);
}
}
至此,通过动态代理的方式将插件织入到executor中,并生成了DefaultSqlSession。
下一步是调用SqlSession.getMapper()获取目标mapper。
DefaultSqlSession:
@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
Configuration:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
MapperRegistry:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 根据类型,从knownMappers中获取mapperProxyFactory
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); // 构建mapper的代理对象
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
MapperProxyFactory:
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
// 通过动态代理的方式创建代理对象,mapperProxy实现了InvocationHandler。
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
至此,mapper创建流程介绍完成,下一步将分析sql的执行流程。