• mybatis笔记3 一些原理的理解


    1,mybatis流程跟踪,原理理解

      基本思路: 从SqlSessionFactory的初始化出发,观察资源的准备和环境的准备,以及实现持久层的一些过程;

    进入SqlSessionFactoryBean类,发现先执行的是

    image

    然后是:

    image

    在初始化类之后,做的准备工作如下:

    public void afterPropertiesSet() throws Exception {
        notNull(dataSource, "Property 'dataSource' is required");//1,检查spring准备的datasource是否ok
        notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");//2,检查空构造方法的sqlSessionFactoryBuilder是否准备好

        this.sqlSessionFactory = buildSqlSessionFactory();//3,利用配置的属性,构造sqlSessionFactory
      }

    构造细节如下:方法有点长,注意注释这个是流程,之后我画一个图来加深理解;

    protected SqlSessionFactory buildSqlSessionFactory() throws IOException {

       Configuration configuration;

       XMLConfigBuilder xmlConfigBuilder = null;
       if (this.configLocation != null) {//1,检查是否有配置configLocation,即mybatis的整体配置文件,非mapper文件,如果有加载进去,没有,构造一个空的
         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);
       }

       if (this.objectFactory != null) {//2,检查对象工厂,如果有设置进去,没有留空
         configuration.setObjectFactory(this.objectFactory);
       }

       if (this.objectWrapperFactory != null) {//3,检查对象装饰工厂,如果有设置进去,没有留空

         configuration.setObjectWrapperFactory(this.objectWrapperFactory);
       }

       if (hasLength(this.typeAliasesPackage)) {//4,检查包的简称,如果有注册进去
         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)) {//5,检查类的简称,如果有注册进去
         for (Class<?> typeAlias : this.typeAliases) {
           configuration.getTypeAliasRegistry().registerAlias(typeAlias);
           if (logger.isDebugEnabled()) {
             logger.debug("Registered type alias: '" + typeAlias + "'");
           }
         }
       }

       if (!isEmpty(this.plugins)) {//6,检查插件,如果有注册进去
         for (Interceptor plugin : this.plugins) {
           configuration.addInterceptor(plugin);
           if (logger.isDebugEnabled()) {
             logger.debug("Registered plugin: '" + plugin + "'");
           }
         }
       }

       if (hasLength(this.typeHandlersPackage)) {//7,检查类型转换类包,如果有注册进去
         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)) {//8,检查类型转换类,如果有注册进去
         for (TypeHandler<?> typeHandler : this.typeHandlers) {
           configuration.getTypeHandlerRegistry().register(typeHandler);
           if (logger.isDebugEnabled()) {
             logger.debug("Registered type handler: '" + typeHandler + "'");
           }
         }
       }

       if (xmlConfigBuilder != null) {//9,检查是否有xml的构造器,如果有,直接使用构造器构造
         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) {//10,检查事物工厂,如果没有,构造一个spring管理的事物工厂
         this.transactionFactory = new SpringManagedTransactionFactory();
       }

    //11,构造环境变量

       Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);
       configuration.setEnvironment(environment);

       if (this.databaseIdProvider != null) {
         try {//12,检查是否配置了db id,如果有,设置到配置的类中
           configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
         } catch (SQLException e) {
           throw new NestedIOException("Failed getting a databaseId", e);
         }
       }

       if (!isEmpty(this.mapperLocations)) {//13,把配置的mapper弄进来总配置文件里
         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");
         }
       }

       return this.sqlSessionFactoryBuilder.build(configuration);//14,最后通过得到的配置类来构造一个sqlsessionFactory工厂
    }

    设置好属性之后,执行

    image

    得到factory构造的bean,即sqlSessionFactory,

    最后容器启动成功的事件监控

    public void onApplicationEvent(ApplicationEvent event) {
       if (failFast && event instanceof ContextRefreshedEvent) {
         // fail-fast -> check all statements are completed
         this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
       }
    }

    以上是资源的准备,下面来一次增删改查的跟踪,观察内部的工作原理;

    查询单条记录的过程:

    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
      try {
        MappedStatement ms = configuration.getMappedStatement(statement);//1,通过转换,得到存储的mapperedStatement
        List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);//2,转换成jdbc代码执行
        return result;
      } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
      } finally {
        ErrorContext.instance().reset();
      }
    }

    内部就像是一台精密的仪器,去除了大量的模版jdbc代码;

  • 相关阅读:
    xamarin ios html5 video.js 无法播放
    限制WPF textbox 字符最大值
    .net 客户端 WCF Binding 多次迭代
    10款无需编程的App DIY开发工具
    国外一些好用的UX/UI设计工具和资源分享
    成功网页设计师的七大必备技能
    提升编程能力的11个技巧
    2015程序员推荐书单
    前端工作流程自动化——Grunt/Gulp 自动化
    HTML5初学者福利!11个在线学习网站推荐
  • 原文地址:https://www.cnblogs.com/snidget/p/3582364.html
Copyright © 2020-2023  润新知