MyBatis源码分析_获取sqlSessionFactory对象

/**
 * 1、获取sqlSessionFactory对象:
 *         解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
 *         注意:【MappedStatement】:代表一个增删改查的详细信息
 * 
 * 2、获取sqlSession对象
 *         返回一个DefaultSQlSession对象,包含Executor和Configuration;
 *         这一步会创建Executor对象;
 * 
 * 3、获取接口的代理对象(MapperProxy)
 *         getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象
 *         代理对象里面包含了,DefaultSqlSession(Executor)
 * 4、执行增删改查方法
 * 
 * 总结:
 *     1、根据配置文件(全局,sql映射)初始化出Configuration对象
 *     2、创建一个DefaultSqlSession对象,
 *         他里面包含Configuration以及
 *         Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
 *  3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
 *  4、MapperProxy里面有(DefaultSqlSession);
 *  5、执行增删改查方法:
 *          1)、调用DefaultSqlSession的增删改查(Executor);
 *          2)、会创建一个StatementHandler对象。
 *              (同时也会创建出ParameterHandler和ResultSetHandler)
 *          3)、调用StatementHandler预编译参数以及设置参数值;
 *              使用ParameterHandler来给sql设置参数
 *          4)、调用StatementHandler的增删改查方法;
 *          5)、ResultSetHandler封装结果
 *  注意:
 *      四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);
 */

 MyBatis源码分析_获取sqlSessionFactory对象

 

 MyBatis源码分析_获取sqlSessionFactory对象

调用了自己三个参数的build 方法 

MyBatis源码分析_获取sqlSessionFactory对象

MyBatis源码分析_获取sqlSessionFactory对象

MyBatis源码分析_获取sqlSessionFactory对象

MyBatis源码分析_获取sqlSessionFactory对象

 

MyBatis源码分析_获取sqlSessionFactory对象

 

进入  settingsElement(settings); 方法里面,还是这个类

private void settingsElement(Properties props) throws Exception {
	configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
	configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
	configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
	configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
	configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
	configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
	configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
	configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
	configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
	configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
	configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
	configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
	configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
	configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
	configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
	configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
	configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
	configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
	configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
	configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
	configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
	configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
	configuration.setLogPrefix(props.getProperty("logPrefix"));
	@SuppressWarnings("unchecked")
	Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty("logImpl"));
	configuration.setLogImpl(logImpl);
	configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
}

这里 调用 configuration.setXxx,没有设置值的这里会给默认值,解析每一个设置的内容并且保存在 configuration 中

MyBatis源码分析_获取sqlSessionFactory对象

MyBatis源码分析_获取sqlSessionFactory对象

 MyBatis源码分析_获取sqlSessionFactory对象

 mapperElement 方法同样的还是在 XMLConfigBuilder 类里面

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());
		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.");
	  }
	}
  }
}
}

MyBatis源码分析_获取sqlSessionFactory对象

 MyBatis源码分析_获取sqlSessionFactory对象

 MyBatis源码分析_获取sqlSessionFactory对象

 

 MyBatis源码分析_获取sqlSessionFactory对象

 

  public void parseStatementNode() {
    String id = context.getStringAttribute("id");
    String databaseId = context.getStringAttribute("databaseId");

    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
      return;
    }

    Integer fetchSize = context.getIntAttribute("fetchSize");
    Integer timeout = context.getIntAttribute("timeout");
    String parameterMap = context.getStringAttribute("parameterMap");
    String parameterType = context.getStringAttribute("parameterType");
    Class<?> parameterTypeClass = resolveClass(parameterType);
    String resultMap = context.getStringAttribute("resultMap");
    String resultType = context.getStringAttribute("resultType");
    String lang = context.getStringAttribute("lang");
    LanguageDriver langDriver = getLanguageDriver(lang);

    Class<?> resultTypeClass = resolveClass(resultType);
    String resultSetType = context.getStringAttribute("resultSetType");
    StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);

    String nodeName = context.getNode().getNodeName();
    SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    boolean useCache = context.getBooleanAttribute("useCache", isSelect);
    boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

    // Include Fragments before parsing
    XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
    includeParser.applyIncludes(context.getNode());

    // Parse selectKey after includes and remove them.
    processSelectKeyNodes(id, parameterTypeClass, langDriver);
    
    // Parse the SQL (pre: <selectKey> and <include> were parsed and removed)
    SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
    String resultSets = context.getStringAttribute("resultSets");
    String keyProperty = context.getStringAttribute("keyProperty");
    String keyColumn = context.getStringAttribute("keyColumn");
    KeyGenerator keyGenerator;
    String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
    keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
    if (configuration.hasKeyGenerator(keyStatementId)) {
      keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
      keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
          configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
          ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
    }

    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered, 
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
  }

这个方法就是把Mapper便签里面的每一个元素的标签解析出来,封装成一个 MappedStatement ,一个 MappedStatement就代表一个增删该查标签的详细信息

MyBatis源码分析_获取sqlSessionFactory对象

 MyBatis源码分析_获取sqlSessionFactory对象

 MappedStatement 还是封装在configuration对象中,整个初始化过程启动都是在在向configuration对象中封装类容

MyBatis源码分析_获取sqlSessionFactory对象

 一路返回,解析完Mapper文件

MyBatis源码分析_获取sqlSessionFactory对象

 

MyBatis源码分析_获取sqlSessionFactory对象

MyBatis源码分析_获取sqlSessionFactory对象

 

 MyBatis源码分析_获取sqlSessionFactory对象

 

MyBatis源码分析_获取sqlSessionFactory对象

 

 mapperRegistry 里面对象这每一个Mapper的代理对象工厂,用来产生代理对象

 

MyBatis源码分析_获取sqlSessionFactory对象

 

 

MyBatis源码分析_获取sqlSessionFactory对象