`

mybatis 源码分析之初始化

 
阅读更多

mybatis 的配置文件解析又XMLConfigBuilder的parseConfiguration方法来完成,解析结果都存在Configuration这个类中

 

private void parseConfiguration(XNode root) {//根节点
    try {
     //解析别名
      typeAliasesElement(root.evalNode("typeAliases"));
     //解析插件
      pluginElement(root.evalNode("plugins"));
      //对象工厂解析
    //MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成
      objectFactoryElement(root.evalNode("objectFactory"));
      //
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      //解析属性
      propertiesElement(root.evalNode("properties"));
       //解析mybatis参数
      settingsElement(root.evalNode("settings"));
      //解析环境
      environmentsElement(root.evalNode("environments"));
      //解析类型处理
      typeHandlerElement(root.evalNode("typeHandlers"));
     //解析mapper映射文件
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

 别名解析

 private void typeAliasesElement(XNode parent) {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String alias = child.getStringAttribute("alias");
        String type = child.getStringAttribute("type");
        try {
          Class<?> clazz = Resources.classForName(type);
          if (alias == null) {
             //没有设别名时
            typeAliasRegistry.registerAlias(clazz);
          } else {
           //有设别名
            typeAliasRegistry.registerAlias(alias, clazz);
          }
        } catch (ClassNotFoundException e) {
          throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
        }
      }
    }
  }
public void registerAlias(Class type) {
    
    String alias = type.getSimpleName();
      //从注解上获取
    Alias aliasAnnotation = (Alias) type.getAnnotation(Alias.class);
    if (aliasAnnotation != null) {
      alias = aliasAnnotation.value();
    } 
    registerAlias(alias, type);
  }
public void registerAlias(String alias, Class value) {
    assert alias != null;
    String key = alias.toLowerCase();
    if (TYPE_ALIASES.containsKey(key) && !TYPE_ALIASES.get(key).equals(value.getName()) && TYPE_ALIASES.get(alias) != null) {
      if (!value.equals(TYPE_ALIASES.get(alias))) {
        throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(alias).getName() + "'.");
      }
    }
 //存入hashMaplim
    TYPE_ALIASES.put(key, value);
  }


 插件解析

 

 

private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String interceptor = child.getStringAttribute("interceptor");
         //获取插件属性
        Properties properties = child.getChildrenAsProperties();
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
        interceptorInstance.setProperties(properties);
        //加入到configuration类的插件执行链里面,其实就是List
        configuration.addInterceptor(interceptorInstance);
      }
    }

 z工厂对象解析

 

 

private void objectFactoryElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties properties = context.getChildrenAsProperties();
      ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance();
      factory.setProperties(properties);
     //替换默认的DefaultObjectFactory工厂
      configuration.setObjectFactory(factory);
    }
  }
  

 解析属性

 

 

 private void propertiesElement(XNode context) throws Exception {
    if (context != null) {
      Properties defaults = context.getChildrenAsProperties();
      String resource = context.getStringAttribute("resource");
      String url = context.getStringAttribute("url");
      if (resource != null && url != null) {
        throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.");
      }
      if (resource != null) {
        defaults.putAll(Resources.getResourceAsProperties(resource));
      } else if (url != null) {
        defaults.putAll(Resources.getUrlAsProperties(url));
      }
      Properties vars = configuration.getVariables();
      if (vars != null) {
        defaults.putAll(vars);
      }
      parser.setVariables(defaults);
      configuration.setVariables(defaults);
    }
  }

 解析mybatis参数

 

 

 private void settingsElement(XNode context) throws Exception {
    if (context != null) {
      Properties props = context.getChildrenAsProperties();
      // Check that all settings are known to the configuration class
      MetaClass metaConfig = MetaClass.forClass(Configuration.class);
      for (Object key : props.keySet()) {
     //严重参数是否合法
        if (!metaConfig.hasSetter(String.valueOf(key))) {
          throw new BuilderException("The setting " + key + " is not known.  Make sure you spelled it correctly (case sensitive).");
        }
      }
      configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(stringValueOf(props.getProperty("autoMappingBehavior"), "PARTIAL")));
      configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
      configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
      configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), true));
      configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
      configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
      configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
      configuration.setDefaultExecutorType(ExecutorType.valueOf(stringValueOf(props.getProperty("defaultExecutorType"), "SIMPLE")));
      configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
    }
  }

 

 

环境解析

 private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dsFactory.getDataSource());
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }

 环境解析

rivate void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
         //事物管理器
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          //数据源
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dsFactory.getDataSource());
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }

 类型处理器解析

 private void typeHandlerElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String javaType = child.getStringAttribute("javaType");
        String jdbcType = child.getStringAttribute("jdbcType");
        String handler = child.getStringAttribute("handler");

        Class<?> javaTypeClass = resolveClass(javaType);
        TypeHandler typeHandlerInstance = (TypeHandler) resolveClass(handler).newInstance();
        //也是解析后放在hashmap里
     //  private final Map<Class<?>, Map<JdbcType, TypeHandler>> TYPE_HANDLER_MAP = new HashMap<Class<?>, Map<JdbcType, TypeHandler>>();
        if (jdbcType == null) {
          typeHandlerRegistry.register(javaTypeClass, typeHandlerInstance);
        } else {
          typeHandlerRegistry.register(javaTypeClass, resolveJdbcType(jdbcType), typeHandlerInstance);
        }
      }
    }
  }

 mapper映射文件

 

private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String resource = child.getStringAttribute("resource");
        String url = child.getStringAttribute("url");
        InputStream inputStream;
        if (resource != null && url == null) {
          ErrorContext.instance().resource(resource);
          inputStream = Resources.getResourceAsStream(resource);
          //构建mapper xml 解析
          XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
          mapperParser.parse();
        } else if (url != null && resource == null) {
          ErrorContext.instance().resource(url);
          inputStream = Resources.getUrlAsStream(url);
          XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
          mapperParser.parse();
        } else {
          throw new BuilderException("A mapper element may only specify a url or resource, but not both.");
        }
      }
    }
  }

public void parse() {
     //判断是否已经解析过
    if (!configuration.isResourceLoaded(resource)) {
       //获取mapper 跟节点并解析
      configurationElement(parser.evalNode("/mapper"));
     //表示此resource已经解析
      configuration.addLoadedResource(resource);
      //根据mapper的配置文件命名空间,查找对应的mapper类
      bindMapperForNamespace();
    }
    parsePendingChacheRefs();
    parsePendingStatements();
  }

 private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      builderAssistant.setCurrentNamespace(namespace);
      cacheRefElement(context.evalNode("cache-ref"));
      cacheElement(context.evalNode("cache"));
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      sqlElement(context.evalNodes("/mapper/sql"));
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new RuntimeException("Error parsing Mapper XML. Cause: " + e, e);
    }
  }

 

 

分享到:
评论

相关推荐

    Mybatis源码分析.pdf

    总结起来,MyBatis源码分析涵盖了从配置加载到数据库操作的全过程,涉及到了配置解析、SQL执行、结果映射等多个关键环节,以及Executor、StatementHandler等核心组件。通过深入学习MyBatis的源码,开发者不仅可以...

    Java架构师之源码分析专题SpringBoot2.x、Spring5、SpringMVC、Mybatis源码分析

    源码分析将涵盖`ApplicationContext`的初始化过程,AOP(面向切面编程)的实现,以及事件传播机制。通过对这些核心组件的了解,可以提高你的Spring应用性能和可维护性。 SpringMVC作为Spring框架的一部分,负责处理...

    MyBatis源码详解学习.zip

    SqlSessionFactory根据配置文件(如mybatis-config.xml)初始化,提供了一种线程安全的方式来获取SqlSession,后者是执行SQL命令的接口。 在执行SQL时,MyBatis的Executor执行器起着核心作用。它有SimpleExecutor、...

    mybatis3.x源码深度解析与最佳实践.pdf

    本系列源码解析的方式将从 MyBatis 的源码入手,深入分析 MyBatis 的设计思路和实现机制。 2. 容器的加载与初始化 2.1 config 文件解析 XMLConfigBuilder.parseConfiguration 方法是 MyBatis 中的核心方法之一,...

    MyBatis源码demo

    《MyBatis源码分析与实战应用》 在IT行业中,MyBatis作为一个轻量级的持久层框架,因其灵活性和高效性而被广泛应用。它将SQL语句与Java代码相结合,提供了比传统JDBC更方便的数据操作方式。本文将深入探讨MyBatis的...

    Mybatis源码分析.md

    ### Mybatis源码分析 #### 1. 解析配置文件,创建SQLSessionFactory 在MyBatis框架中,创建`SQLSessionFactory`是初始化整个框架的重要步骤之一。这一过程涉及到了配置文件的读取与解析,以及如何构建出可以用于...

    java-ORM框架Mybatis源码分析

    首先,MyBatis的初始化过程始于`SqlSessionFactoryBuilder`,它负责读取配置文件,构建`SqlSessionFactory`。配置文件通常包含数据源信息、Mapper XML文件的位置以及MyBatis全局设置。`SqlSessionFactory`是整个...

    Mybatis源码分析-上课笔记1

    在分析MyBatis源码时,可以采用宏观和微观两种视角。宏观上理解整个框架的架构和流程,微观上深入到具体的类和方法,通过阅读和调试代码来理解其实现细节。同时,绘制流程图或UML图能帮助更好地梳理组件间的交互。 ...

    源码分析专题之Mybatis课程一之源码分析与实现2

    在初版实现中,我们可以关注如何初始化 SqlSessionFactory,这通常涉及读取 mybatis-config.xml 文件,创建 Configuration 实例,然后通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory。 4. **再来一个 2.0 ...

    源码分析专题之Mybatis课程一之源码分析与实现1

    对MyBatis源码的分析通常从XML配置文件解析开始,这是整个框架初始化的关键步骤。主要关注以下两个切入点: - **XMLConfigBuilder#parseConfiguration**:解析mybatis-config.xml文件,生成Configuration对象,...

    mybatis源码自动生成工具

    MyBatis源码自动生成工具是一款实用的开发辅助软件,专为简化MyBatis框架的初始化工作而设计。它能够帮助开发者快速生成包括XML配置文件和对应的Java类在内的基础架构代码,极大地提高了开发效率,降低了出错的可能...

    Mybatis系列教程Mybatis源码剖析共15页.pd

    【描述】"Mybatis系列教程Mybatis源码剖析共15页.pdf.zip" 是一个压缩文件,包含了15页关于Mybatis源码分析的教程内容。通过解压这个.zip文件,用户可以获取到PDF格式的教程文档,便于学习和查阅。这15页的内容通常...

    mybatis两天视频教程+源码+笔记

    - **使用场景:**在应用程序启动时通过配置文件或者直接指定配置的方式初始化。 **2. SqlSessionFactory:** - **功能:**用于创建SqlSession的工厂类。 - **使用场景:**每次需要操作数据库时,都需要通过...

    Mybatis 源码项目搭建以及主流程分析

    通过对Mybatis源码的阅读和项目实践,我们可以更深入地了解其工作原理,提升我们的编程技巧,更好地利用Mybatis进行数据库操作。同时,对设计模式的理解也有助于我们编写出更加灵活、可维护的代码。

    基于Java的HBNU后端学习之SpringBoot、Hibernate及MyBatis源码解析

    本次分享的项目《基于Java的HBNU后端学习之SpringBoot、Hibernate及MyBatis源码解析》为我们提供了一个深入了解这些框架内部工作机制的窗口。 该项目详细记录了湖北师范大学后端开发团队在实际开发中对SpringBoot、...

    Mybatis:Mybatis源码分析

    1. **SqlSessionFactoryBuilder**:Mybatis的初始化始于`SqlSessionFactoryBuilder`,它负责读取配置文件(XML或Java Config),构建`SqlSessionFactory`。这个过程包括解析配置、加载映射文件、创建Configuration...

    MyBatis 源码分析 之SqlSession接口和Executor类

    MyBatis是一个流行的Java持久层框架,它简化了数据库操作,允许开发者将SQL查询与Java代码直接集成。...在源码分析中,对这两个组件的深入理解可以帮助开发者优化性能,排查问题,以及自定义扩展MyBatis的功能。

    mybatis项目源码及单元测试

    - `SqlSessionFactoryBuilder`: 用于构建 `SqlSessionFactory`,它是 MyBatis 的核心,负责初始化和配置 MyBatis。 - `SqlSessionFactory`: 会话工厂,用于创建 `SqlSession` 对象,`SqlSession` 是执行 SQL 的...

    基于Java语言的mybatis20240805版本设计原理及源码分析

    源码分析方面,MyBatis源码主要由以下几个核心组件构成: 1. SqlSessionFactoryBuilder:用于构建SqlSessionFactory实例,它是一个工厂模式的应用,其目的是为了创建SqlSession实例。 2. SqlSessionFactory:一个...

    mybatis学习的源码

    在深入探讨MyBatis源码之前,先要理解MyBatis的基本概念和工作原理。 MyBatis的核心组件包括SqlSession、SqlSessionFactory和Mapper。SqlSession是与数据库交互的会话对象,用于执行SQL命令;SqlSessionFactory则是...

Global site tag (gtag.js) - Google Analytics