在获取SqlSessionFactory对象时,跟踪源码,是发现通过一个builder()方法来得到的,build()方法如下:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }
在build()方法中,有这么一行代码:XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);这个主要是用来解析流化的配置文件,外部设置的environment对象与properties对象。这里看下XMLConfigBuilder这个类
public class XMLConfigBuilder extends BaseBuilder { private boolean parsed; //是否已经解析过mybatis配置文件,如果已经解析过为true private final XPathParser parser; //xml解析 private String environment; private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory(); public XMLConfigBuilder(Reader reader) { this(reader, null, null); } public XMLConfigBuilder(Reader reader, String environment) { this(reader, environment, null); } public XMLConfigBuilder(Reader reader, String environment, Properties props) { this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props); } public XMLConfigBuilder(InputStream inputStream) { this(inputStream, null, null); } public XMLConfigBuilder(InputStream inputStream, String environment) { this(inputStream, environment, null); } public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) { this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); } private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { super(new Configuration()); ErrorContext.instance().resource("SQL Mapper Configuration"); this.configuration.setVariables(props); this.parsed = false; this.environment = environment; this.parser = parser; }
//解析mybatis配置文件,返回configuration对象 public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }
//解析配置文件的各个节点,解析的结果保存到configuration对象中 private void parseConfiguration(XNode root) { try { //issue #117 read properties first propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } } }
最终都是执行private XMLConfigBuilder(XPathParser parser, String environment, Properties props)这个方法,在这方法里有这么一行代码 super(new Configuration());
这里是调用XMLConfigBuilder的父类BaseBuilder的构造器,同时初始化configuration对象。追踪下configuration这个对象的初始化过程:
public Configuration() { typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class); typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class); typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); typeAliasRegistry.registerAlias("FIFO", FifoCache.class); typeAliasRegistry.registerAlias("LRU", LruCache.class); typeAliasRegistry.registerAlias("SOFT", SoftCache.class); typeAliasRegistry.registerAlias("WEAK", WeakCache.class); typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class); typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class); typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class); typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class); typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class); typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class); typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class); typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class); typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class); typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class); typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class); typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class); languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class); languageRegistry.register(RawLanguageDriver.class); }
其中typeAliasRegistry是类型别名注册表,主要是用来设置别名的,mybatis配置文件中可以设置别名,这里均通过这个注册表来保存到map中。
这里追踪下XMLConfigBuilder的父类BaseBuilder,这里面有三个重要的属性
public abstract class BaseBuilder { protected final Configuration configuration; //mybatis配置文件解析后均存储在该对象中 protected final TypeAliasRegistry typeAliasRegistry; //别名注册表,用于解析配置文件中别名的设置 protected final TypeHandlerRegistry typeHandlerRegistry; //处理器注册表,用于解析配置文件中处理器的设置 public BaseBuilder(Configuration configuration) { this.configuration = configuration; this.typeAliasRegistry = this.configuration.getTypeAliasRegistry(); this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry(); } }
至此,XMLConfigBuilder类已经解析完成,该类主要是解析mybatis配置文件的各个子节点的信息,例如常用的<properties></properties>节点,<settings></settings>节点,<environment></environment>节点,<mappers></mappers>节点,并保存到configuration对象中