目录
private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode("properties")); //issue #117 read properties first typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); settingsElement(root.evalNode("settings")); environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); //解析mapper标签 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
// XMLConfigBuilder.mapperElement 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) { //resource配置方式走这里 ErrorContext.instance().resource(resource); //根据路径读取文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //生成xmlMapperBuilder对象 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); //解析 mapperParser.parse(); } else if (resource == null && url != null && mapperClass == null) { //rul配置方式走这里 ErrorContext.instance().resource(url); InputStream inputStream = Resources.getUrlAsStream(url); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url == null && mapperClass != null) { //mapperClass方式走这里 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."); } } } } }
//XmlMapperBuilder.parse() public void parse() { //判断是否已经加载过 if (!configuration.isResourceLoaded(resource)) { // xml -> configuration configurationElement(parser.evalNode("/mapper")); // 加入到已解析列表 configuration.addLoadedResource(resource); //绑定命名空间 bindMapperForNamespace(); } parsePendingResultMaps(); parsePendingChacheRefs(); parsePendingStatements(); }
//解析mapper及子孙标签 //XmlMapperBuilder.configurationElement private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); if (namespace.equals("")) { throw new BuilderException("Mapper's namespace cannot be empty"); } builderAssistant.setCurrentNamespace(namespace); //缓存的引用 cacheRefElement(context.evalNode("cache-ref")); //缓存 cacheElement(context.evalNode("cache")); //参数 parameterMapElement(context.evalNodes("/mapper/parameterMap")); //返回结果 resultMapElements(context.evalNodes("/mapper/resultMap")); //解析sql片段 sqlElement(context.evalNodes("/mapper/sql")); //解析 select|insert|update|delete 这几个标签 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e); } }
具体的解析select|insert|update|delete 标签
//XmlMapperBuilder.configurationElement private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) { for (XNode context : list) { final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); try { statementParser.parseStatementNode(); } catch (IncompleteElementException e) { configuration.addIncompleteStatement(statementParser); } } } public void parseStatementNode() { //这里省略了部分非必要代码逻辑 // 这里是生成sqlSource对象 ,这是sql的核心 // sqlSource 的实现子类有DynamicSqlSource/staticSqlSource/RawSqlSource/ProviderSqlSource SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass); // 省略非必要代码 // 生成 MappedStatement 并加入configuration builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); }
调用链如下:
1、confirguration.addMapper()
2、MapperRegistry.addMapper()
public <T> void addMapper(Class<T> type) { if (type.isInterface()) { if (hasMapper(type)) { throw new BindingException("Type " + type + " is already known to the MapperRegistry."); } boolean loadCompleted = false; try { //new 一个工厂类放到map里 knownMappers.put(type, new MapperProxyFactory<T>(type)); // MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } }
调用链如下:
1、SqlSession.getMapper()
2、configuration.<T>getMapper(type, this);
3、mapperRegistry.getMapper(type, sqlSession);
4、mapperProxyFactory.newInstance(sqlSession); // 这就是刚才注册时 ,生成的工厂对象
5、mapperProxy.invoke();// 核心的逻辑
public T newInstance(SqlSession sqlSession) { //生成mapperProxy, 其实现了InvocationHandler , 是jdk的动态代理 final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); //生成代理 , 注意 这里的代理是比较特殊的 , 因为其没有具体实现 return newInstance(mapperProxy); } protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); }
MapperProxy.invoke()
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { try { //如果是object 普通方法,直接调用 return method.invoke(this, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } //找到mapperMehtod对象 //这个对象里包装了一个mapper的sql标签 /** private final SqlCommand command; private final MethodSignature method; */ final MapperMethod mapperMethod = cachedMapperMethod(method); //执行 return mapperMethod.execute(sqlSession, args); }
public Object execute(SqlSession sqlSession, Object[] args) { //已selectOne为例 , 其他代码忽略 Object param = method.convertArgsToSqlCommandParam(args); //这里是通过sqlSession -> executor 来执行查询的 result = sqlSession.selectOne(command.getName(), param); }