MyBatis框架的使用及源码分析(三) 配置篇 Configuration

从上文<MyBatis框架中Mapper映射配置的使用及原理解析(二) 配置篇 SqlSessionFactoryBuilder,XMLConfigBuilder> 我们知道XMLConfigBuilder调用parse()方法解析Mybatis配置文件,生成Configuration对象。

Configuration类主要是用来存储对Mybatis的配置文件及mapper文件解析后的数据,Configuration对象会贯穿整个Mybatis的执行流程,为Mybatis的执行过程提供必要的配置信息。

我们先贴出一个包含了所有属性的mybatis-Config.xml实例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="org/apache/ibatis/databases/blog/blog-derby.properties" /> <settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="false" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25" />
</settings> <typeAliases>
<typeAlias alias="Author" type="org.apache.ibatis.domain.blog.Author" />
<typeAlias alias="Blog" type="org.apache.ibatis.domain.blog.Blog" />
</typeAliases> <typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR"
handler="org.apache.ibatis.builder.CustomStringTypeHandler" />
</typeHandlers> <objectFactory type="org.apache.ibatis.builder.ExampleObjectFactory">
<property name="objectFactoryProperty" value="100" />
</objectFactory> <plugins>
<plugin interceptor="org.apache.ibatis.builder.ExamplePlugin">
<property name="pluginProperty" value="100" />
</plugin>
</plugins> <environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value="" />
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments> <databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver" />
<property name="DB2" value="db2" />
<property name="Oracle" value="oracle" />
</databaseIdProvider> <mappers>
<mapper resource="org/apache/ibatis/builder/AuthorMapper.xml" />
<mapper resource="org/apache/ibatis/builder/BlogMapper.xml" />
</mappers>
</configuration>

再对照看一看Configuration类的成员变量和构造方法:

package org.apache.ibatis.session;

public class Configuration {

/**
* MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,
* 比如设置不同的开发、测试、线上配置,在每个配置中可以配置事务管理器和数据源对象.
*/
protected Environment environment;
  //允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false。
protected boolean safeRowBoundsEnabled = false;
//允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为false
protected boolean safeResultHandlerEnabled = true;
//是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。
protected boolean mapUnderscoreToCamelCase = false;
  //当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods).
protected boolean aggressiveLazyLoading = true;
/是否允许单一语句返回多结果集(需要兼容驱动)
protected boolean multipleResultSetsEnabled = true;
//允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。
protected boolean useGeneratedKeys = false;
  //使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。
protected boolean useColumnLabel = true;
//配置全局性的cache开关
protected boolean cacheEnabled = true;
/*指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。
注意基本类型(int、boolean等)是不能设置成 null 的。*/
protected boolean callSettersOnNulls = false;
//指定 MyBatis 增加到日志名称的前缀。
protected String logPrefix;
//指定 MyBatis 所用日志的具体实现,未指定时将自动查找
protected Class <? extends Log> logImpl;
/*MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。*/
protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
/*当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。
某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。*/
protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
//指定哪个对象的方法触发一次延迟加载。
protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));
//设置超时时间,它决定驱动等待数据库响应的秒数。
protected Integer defaultStatementTimeout;
/*配置默认的执行器。
SIMPLE 就是普通的执行器;
REUSE 执行器会重用预处理语句(prepared statements);
BATCH 执行器将重用语句并执行批量更新。*/
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
/**
* 指定 MyBatis 应如何自动映射列到字段或属性。
* NONE 表示取消自动映射;
* PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。
* FULL 会自动映射任意复杂的结果集(无论是否嵌套)。
*/
protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;

//这里配置的属性可以在整个配置文件中使用来替换需要动态配置的属性值
    protected Properties variables = new Properties();

  //对象创建工厂,默认的实现类DefaultObjectFactory,用来创建对象,比如传入List.class,利用反射返回ArrayList的实例
protected ObjectFactory objectFactory = new DefaultObjectFactory();
//对象包装工厂,默认实现类是DefaultObjectWrapperFactory,包装Object实例
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
//注册Mapper
protected MapperRegistry mapperRegistry = new MapperRegistry(this);
//延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。
protected boolean lazyLoadingEnabled = false;
//指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具
protected ProxyFactory proxyFactory;
//数据库类型id,MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性
protected String databaseId;

  /**
   * 指定一个提供Configuration实例的类. 这个被返回的Configuration实例是用来加载被反序列化对象的懒加载属性值.

* 这个类必须包含一个签名方法static Configuration getConfiguration(). (从 3.2.3 版本开始)

*/
    protected Class<?> configurationFactory;

  //拦截器链
protected final InterceptorChain interceptorChain = new InterceptorChain();
//TypeHandler注册
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
//别名和具体类注册
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
//这个是指定解析的驱动,比如你可以使用velocity模板引擎来替代xml文件,默认是XMLLanguageDriver,也就是使用xml文件来写sql语句
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();

//对应Mapper.xml里配置的Statement
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
//对应Mapper.xml里配置的cache
protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
//对应Mapper.xml里的ResultMap
protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
//对应Mapper.xml里的ParameterMap
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
//主键生成器
protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");
//存储已经加载过的mapper xml资源,见MapperAnnotationBuilder#loadXmlResource
protected final Set<String> loadedResources = new HashSet<String>();
//存储已经解析过的mapper对应的xml节点
protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
//存储所有未处理的
protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
//存储所有未处理的缓存信息
protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
//存储所有未处理ResultMap的映射信息
protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();

/*
     * A map holds cache-ref relationship. The key is the namespace that
     * references a cache bound to another namespace and the value is the
     * namespace which the actual cache is bound to.
     */
    protected final Map<String, String> cacheRefMap = new HashMap<String, String>();

  public Configuration(Environment environment) {
this();
this.environment = environment;
} public Configuration() {
    //通过使用TypeAliasRegistry来注册一些类的别名
    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);
} }

可以看出Configuration 就是 mybatis-config.xml 的对象实体。

后续我们将结合XMLConfigBuilder,Configuration 讲解Mapper.xml的各元素的解析。

上一篇:负载均衡的时候如何实现相同的session被分配到同一个服务器


下一篇:源特定组播(SSM:Source Specific Multicast)