一、源码分析
1、创建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
·1.1 调用了parse方法,将mybatis配置文件的信息全部解析到一个Configuration对象中(包扩mybatis启动配置信息,数据源,Mapper.xml(sql语句))
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }
1.1.1 解析Mapper.xml
private void mapperElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { if ("package".equals(child.getName())) { String mapperPackage = child.getStringAttribute("name"); configuration.addMappers(mapperPackage); } else { String resource = child.getStringAttribute("resource"); String url = child.getStringAttribute("url"); String mapperClass = child.getStringAttribute("class"); if (resource != null && url == null && mapperClass == null) { ErrorContext.instance().resource(resource); InputStream inputStream = Resources.getResourceAsStream(resource); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url != null && mapperClass == null) { ErrorContext.instance().resource(url); InputStream inputStream = Resources.getUrlAsStream(url); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); //将解析mybatis配置中的mapper节点,里面将解析mapper.xml中的sql mapperParser.parse(); } else if (resource == null && url == null && mapperClass != null) { Class<?> mapperInterface = Resources.classForName(mapperClass); configuration.addMapper(mapperInterface); } else { throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); } } } } }
1.1.1.1 里面执行了(将sql信息封装到了MapperedStatement中(一个MapperedStatement代表了增删改查的详细信息),MappedStatement封装在了Configuration对象中)
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
第一步结束后,最终返回一个 DefaultSqlSessionFactory(保存了Configuration,里面最重要的两个属性)
public class Configuration { protected MapperRegistry mapperRegistry = new MapperRegistry(this); //用于生产mapper代理 protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection"); }
2、通过工厂得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
2.1
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
2.1.1 返回一个 defaultExecutorType = ExecutorType.SIMPLE(默认),还要其他的(BATCH,REUSE),后面会根据这个创建不同的 Executor
configuration.getDefaultExecutorType()
2.1.2
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); //创建4大对象之一的Executor final Executor executor = configuration.newExecutor(tx, execType); //返回DefaultSqlSession(里面包含配置信息,和执行器) 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(); } }
2.1.2.1 根据 ExecutorType,创建不同的执行器,Executor是一个接口,规定了增删改查的所有的方法;
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); } //执行拦截器链(interceptorChain封装了拦截器列表),非常重要,每一个executory的创建都要被拦截 executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
2.1.2.1.1
private final List<Interceptor> interceptors = new ArrayList<Interceptor>(); public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); //执行每一个拦截器的plugin方法,如果没有就跳过 } return target; }
第2步主要就是返回了一个 DefaultSqlSession,里面创建了执行器,封装到DefaultSqlSession中
3、获取代理对象,代理对象去执行增删改查
UserDao mapper = sqlSession.getMapper(UserDao.class);
3.1
public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this); }
3.1.1
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); }
3.1.1.1
@SuppressWarnings("unchecked") public <T> T getMapper(Class<T> type, SqlSession sqlSession) { //knownMappers通过type,获得代理对象 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); } }
3.1.1.1.1
mapperProxyFactory.newInstance(sqlSession);
3.1.1.1.1.1 public class MapperProxy<T> implements InvocationHandler, Serializable (MapperProxy就是一个InvocationHander)
public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }
3.1.1.1.1.1.1 最终创建代理
protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); }