分析MyBatis3的源码首先得从sqlSessionFactory开始,先来看一段spring配置文件中Mybaits的sqlSessionFactory的配置。
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <property name="driverClassName" value="${jdbc.driver}" />
- <property name="url" value="${jdbc.url}" />
- <property name="username" value="${jdbc.username}" />
- <property name="password" value="${jdbc.password}" />
- </bean>
- <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/tiantian/mybatis/mapper/*.xml"/>
- <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />
- </bean>
- <bean id="blogMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
- <property name="mapperInterface"
- value="com.tiantian.mybatis.mapper.BlogMapper" />
- <property name="sqlSessionFactory" ref="sqlSessionFactory" />
- </bean>
spring会调用sqlSessionFactory的无参构造函数创建实例,并将dataSource和映射文件路径注入进去初始化sqlSessionFactory。这里的SqlSessionFactoryBean的实现依赖于mybatis社区自行开发的支持包,我们来看看它是怎么读取xml配置文件创建sessionFactory的:
- protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
- //代表配置的对象
- Configuration configuration;
- //xml配置创建者
- XMLConfigBuilder xmlConfigBuilder = null;
- //spring中注入的配置文件路径,如果不存在使用默认配置
- if (this.configLocation != null) {
- xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
- configuration = xmlConfigBuilder.getConfiguration();
- } else {
- if (logger.isDebugEnabled()) {
- logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
- }
- configuration = new Configuration();
- configuration.setVariables(this.configurationProperties);
- }
- //如果配置了objectFactory使用此配置类
- if (this.objectFactory != null) {
- configuration.setObjectFactory(this.objectFactory);
- }
- //同上
- if (this.objectWrapperFactory != null) {
- configuration.setObjectWrapperFactory(this.objectWrapperFactory);
- }
- //如果配置了typeAliases(实体类别名标签)的基包则不用在configuration文件中配置
- if (hasLength(this.typeAliasesPackage)) {
- String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
- ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
- for (String packageToScan : typeAliasPackageArray) {
- 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 + "'");
- }
- }
- }
- //是否配置mybaits的一些插件
- if (!isEmpty(this.plugins)) {
- for (Interceptor plugin : this.plugins) {
- configuration.addInterceptor(plugin);
- if (logger.isDebugEnabled()) {
- logger.debug("Registered plugin: '" + plugin + "'");
- }
- }
- }
- //是否配置typeHandler的基包
- 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");
- }
- }
- }
- //是否直接配置了typeHandler
- if (!isEmpty(this.typeHandlers)) {
- for (TypeHandler<?> typeHandler : this.typeHandlers) {
- configuration.getTypeHandlerRegistry().register(typeHandler);
- if (logger.isDebugEnabled()) {
- logger.debug("Registered type handler: '" + typeHandler + "'");
- }
- }
- }
- //如果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的环境对象
- Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
- configuration.setEnvironment(environment);
-
- if (this.databaseIdProvider != null) {
- try {
- configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
- } catch (SQLException e) {
- throw new NestedIOException("Failed getting a databaseId", e);
- }
- }
- //是否配置mapperLocations,如果存在解析创建这些mapper,mapper是mybaits管理各种sql的容器
- if (!isEmpty(this.mapperLocations)) {
- for (Resource mapperLocation : this.mapperLocations) {
- if (mapperLocation == null) {
- continue;
- }
-
- try {
- 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");
- }
- }
- //创建sqlSessionFactoryBean
- return this.sqlSessionFactoryBuilder.build(configuration);
- }
从mybatis创建sqlSessionFactoryBean的过程可以看出,mybaits默认使用spring的事务管理功能或者由第三方实现,它自身并没有提供事务管理能力。其次,它拥有跟其它框架差不多的解析xml过程,都是将xml解析成一个Configuration对象随时取用。到这里我们就得到了一个sqlSessionFactoryBean对象(实际是mybatis本身的DefaultSqlSessionFactory对象),我们可以在DAO中注入这个对象并利用openSession的方法获取SqlSession对象从而进行各种数据库操作。
|