要了解MyBatis的的源码,咱们能够看看咱们平时在Spring容器中使用MyBatis的配置文件,找到最基本的入口.java
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:configuration.xml"></property> <property name="mapperLocations" value="classpath:com/sage/mybatis/mapper/*.xml"/> <property name="typeAliasesPackage" value="com.sage.entity" /> </bean>
Spring会调用SqlSessionFactoryBean这个工厂bean的无参构造函数,同时注入dataSource,Mapper文件的路径,进行sqlSessionFactory的初始化.这里面的SqlSessionFactoryBean,使用的是mybatis-spring包.spring
咱们来看一下,MyBatis是如何经过XML配置来建立SqlSessionFactory.sql
protected SqlSessionFactory buildSqlSessionFactory() throws IOException { Configuration configuration; XMLConfigBuilder xmlConfigBuilder = null; if (this.configuration != null) { configuration = this.configuration; if (configuration.getVariables() == null) { configuration.setVariables(this.configurationProperties); } else if (this.configurationProperties != null) { configuration.getVariables().putAll(this.configurationProperties); } } else if (this.configLocation != null) { // 若是传入了MyBatis Config文件的路径,初始化xmlConfigBuilder 并得到里面的配置信息 xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties); configuration = xmlConfigBuilder.getConfiguration(); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Property `configuration` or 'configLocation' not specified, using default MyBatis Configuration"); } configuration = new Configuration(); configuration.setVariables(this.configurationProperties); } if (this.objectFactory != null) { configuration.setObjectFactory(this.objectFactory); } if (this.objectWrapperFactory != null) { configuration.setObjectWrapperFactory(this.objectWrapperFactory); } if (this.vfs != null) { configuration.setVfsImpl(this.vfs); } // 若是在Spring的配置文件中,配置类实体类包的别名typeAliasesPackage if (hasLength(this.typeAliasesPackage)) { String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeAliasPackageArray) { // 不使用MyBatis Config文件里的实体类包别名配置 configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases"); } } } if (!isEmpty(this.typeAliases)) { for (Class<?> typeAlias : this.typeAliases) { configuration.getTypeAliasRegistry().registerAlias(typeAlias); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered type alias: '" + typeAlias + "'"); } } } //若是配置类插件,注册插件,从这咱们能够看到,插件类是实现Interceptor, 配置文件里能够传入数组 if (!isEmpty(this.plugins)) { for (Interceptor plugin : this.plugins) { configuration.addInterceptor(plugin); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered plugin: '" + plugin + "'"); } } } if (hasLength(this.typeHandlersPackage)) { String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeHandlersPackageArray) { configuration.getTypeHandlerRegistry().register(packageToScan); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for type handlers"); } } } if (!isEmpty(this.typeHandlers)) { for (TypeHandler<?> typeHandler : this.typeHandlers) { configuration.getTypeHandlerRegistry().register(typeHandler); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered type handler: '" + typeHandler + "'"); } } } //databaseIdProvider 多数据库支持 在编写Mapper的时候 指定databaseId //用于多数据源的状况,我会放到以后的文章来说解如何使用 if (this.databaseIdProvider != null) {//fix #64 set databaseId before parse mapper xmls try { configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource)); } catch (SQLException e) { throw new NestedIOException("Failed getting a databaseId", e); } } //缓存配置 if (this.cache != null) { configuration.addCache(this.cache); } //若是xmlConfigBuilder存在则开始分析建立Configuration对象 if (xmlConfigBuilder != null) { try { xmlConfigBuilder.parse(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'"); } } catch (Exception ex) { throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex); } finally { ErrorContext.instance().reset(); } } //事务工厂配置 if (this.transactionFactory == null) { this.transactionFactory = new SpringManagedTransactionFactory(); } //设置configuration的环境变量信息 configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource)); //若是指定了mapper文件的路径 if (!isEmpty(this.mapperLocations)) { for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { //将xml的mapper文件进行解析转换 XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments()); xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); } finally { ErrorContext.instance().reset(); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'"); } } } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found"); } } //建立SqlSessionFactory return this.sqlSessionFactoryBuilder.build(configuration); }
从上面的代码咱们能够简单的看出,在初始化SqlSessionFactory的时候,会经过工厂Bean对象,并传入配置参数进行建立的.咱们能够看到,MyBatis自己并不提供事务的支持,使用的是Spring的事务.同时也和大部分框架,将XML解析为配置对象,方便使用.数据库