• sqlSessionFactory创建


     前言

    分析上篇文章的整合的配置文件,我们可以知道配置的bean是成树状结构的,而在树的最顶层是类型为org.mybatis.Spring.SqlSessionFactoryBean的bean,它将其他相关的bean组装在了一起,那么我们的分析就从此类开始。

    sqlSessionFactory创建

     对于配置文件的读取,Spring是通过org.mybatis.Spring.SqlSessionFactoryBean封装了MyBatis中的实现。首先来看一下这个类的类图:

    根据上图对两个感兴趣的接口FactoryBean和InitializingBean。

      ❤ InitializingBean:实现此接口的bean会在初始化时调用其afterPropertiesSet方法来进行bean的逻辑初始化。

      ❤ FactoryBean:一旦某个bean实现此接口,那么通过getBean方法获取bean时其实是获取此类的getObject返回的实例。

    1.sqlSessionFactoryBean的初始化

     查看org.mybatis.Spring.SqlSessionFactoryBean类型的bean在初始化时做了哪些逻辑实现。

    public void afterPropertiesSet() throws Exception {
            Assert.notNull(this.dataSource, "Property 'dataSource' is required");
            Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
            Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null, "Property 'configuration' and 'configLocation' can not specified with together");
            this.sqlSessionFactory = this.buildSqlSessionFactory();
        }

    很显然,此函数的主要目的是对于sqlSessionFactory的初始化,sqlSessionFactory是所有MyBatis功能的基础。

    protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
            XMLConfigBuilder xmlConfigBuilder = null;
            Configuration configuration;
            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) {
                xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)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();
                if (this.configurationProperties != null) {
                    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);
            }
    
            String[] typeHandlersPackageArray;
            String[] var4;
            int var5;
            int var6;
            String packageToScan;
            if (StringUtils.hasLength(this.typeAliasesPackage)) {
                typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, ",; 	
    ");
                var4 = typeHandlersPackageArray;
                var5 = typeHandlersPackageArray.length;
    
                for(var6 = 0; var6 < var5; ++var6) {
                    packageToScan = var4[var6];
                    configuration.getTypeAliasRegistry().registerAliases(packageToScan, this.typeAliasesSuperType == null ? Object.class : this.typeAliasesSuperType);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
                    }
                }
            }
    
            int var27;
            if (!ObjectUtils.isEmpty(this.typeAliases)) {
                Class[] var25 = this.typeAliases;
                var27 = var25.length;
    
                for(var5 = 0; var5 < var27; ++var5) {
                    Class<?> typeAlias = var25[var5];
                    configuration.getTypeAliasRegistry().registerAlias(typeAlias);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Registered type alias: '" + typeAlias + "'");
                    }
                }
            }
    
            if (!ObjectUtils.isEmpty(this.plugins)) {
                Interceptor[] var26 = this.plugins;
                var27 = var26.length;
    
                for(var5 = 0; var5 < var27; ++var5) {
                    Interceptor plugin = var26[var5];
                    configuration.addInterceptor(plugin);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Registered plugin: '" + plugin + "'");
                    }
                }
            }
    
            if (StringUtils.hasLength(this.typeHandlersPackage)) {
                typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeHandlersPackage, ",; 	
    ");
                var4 = typeHandlersPackageArray;
                var5 = typeHandlersPackageArray.length;
    
                for(var6 = 0; var6 < var5; ++var6) {
                    packageToScan = var4[var6];
                    configuration.getTypeHandlerRegistry().register(packageToScan);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Scanned package: '" + packageToScan + "' for type handlers");
                    }
                }
            }
    
            if (!ObjectUtils.isEmpty(this.typeHandlers)) {
                TypeHandler[] var28 = this.typeHandlers;
                var27 = var28.length;
    
                for(var5 = 0; var5 < var27; ++var5) {
                    TypeHandler<?> typeHandler = var28[var5];
                    configuration.getTypeHandlerRegistry().register(typeHandler);
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Registered type handler: '" + typeHandler + "'");
                    }
                }
            }
    
            if (this.databaseIdProvider != null) {
                try {
                    configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
                } catch (SQLException var24) {
                    throw new NestedIOException("Failed getting a databaseId", var24);
                }
            }
    
            if (this.cache != null) {
                configuration.addCache(this.cache);
            }
    
            if (xmlConfigBuilder != null) {
                try {
                    xmlConfigBuilder.parse();
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'");
                    }
                } catch (Exception var22) {
                    throw new NestedIOException("Failed to parse config resource: " + this.configLocation, var22);
                } finally {
                    ErrorContext.instance().reset();
                }
            }
    
            if (this.transactionFactory == null) {
                this.transactionFactory = new SpringManagedTransactionFactory();
            }
    
            configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource));
            if (!ObjectUtils.isEmpty(this.mapperLocations)) {
                Resource[] var29 = this.mapperLocations;
                var27 = var29.length;
    
                for(var5 = 0; var5 < var27; ++var5) {
                    Resource mapperLocation = var29[var5];
                    if (mapperLocation != null) {
                        try {
                            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments());
                            xmlMapperBuilder.parse();
                        } catch (Exception var20) {
                            throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", var20);
                        } 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");
            }
    
            return this.sqlSessionFactoryBuilder.build(configuration);
        }

    从函数中可以看到,尽管我们还是习惯于将MyBatis的配置和Spring的配置独立出来,但是,这并不代表Spring中的配置不支持直接配置。也就是说,在上篇文章的示例中,完全裤取消配置中的configLocation属性,而把其中的属性直接写在sqlSessionFactoryBean中。

    从这个函数中还可以得知,配置文件还可以支持其他多种属性的配置,如configLocation、objectFactory、objectWrapperFactory、typeAliasesPackage、typeAliases、typeHandlersPackage、plugins、typeHandlers、transactionFactory、databaseIdProvider、mapperLocations。

    其实,如果只按照常用的配置,那么我们只需要在函数最开始按照如下方式处理configLocation:

       xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(),null,this.configurationProperties);
        configuration = xmlConfigBuilder.getConfiguration();

     根据configLocation构造XMLConfigBuilder并进行解析,但是,为了体现Spring更强大的兼容性,Spring还整合了MyBatis中其他属性的注入,并通过实例configuration来承载每一步所获取的信息并最终使用sqlSessionFactoryBuilder实例根据解析到的configuration创建sqlSessionFactory实例。

    2.获取SqlSessionFactoryBean实例

     由于sqlSessionFactoryBean实现了FactoryBean接口,所以当通过getBean方法获取对应实例时,其实是获取该类的getObject函数返回的实例,也就是获得初始化后的sqlSessionFactory属性。

    public SqlSessionFactory getObject() throws Exception {
            if (this.sqlSessionFactory == null) {
                this.afterPropertiesSet();
            }
    
            return this.sqlSessionFactory;
        }

     参考:《Spring源码深度解析》 郝佳 编著: 

  • 相关阅读:
    ADPlus
    'telnet' is not recognized as an internal or external command
    图片二进制上传2
    window.opener返回值的用法
    UrlRewriter 重写的问题
    缩略图 水印
    读取二进制图片问题
    正则表达式匹配问题
    .NET读excl数据
    js调用其他页面输出内容
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/10255301.html
Copyright © 2020-2023  润新知