mybatis source analysis (a) parsing configuration

mybatis source analysis (a) parsing configuration

Dian starting from a load mybatis-config.xml

  Use SqlSessionFactoryBuilder parsing mybatis-config.xml, configured SqlSession

        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        this.sqlSession=sqlSessionFactory.openSession();
        this.userMapper=sqlSession.getMapper(UserMapper.class);

 

  mybatis-config.xml:

<? Xml Version = "1.0" encoding = "UTF-8" ?> 
<! DOCTYPE the Configuration 
        the PUBLIC "- // mybatis.org//DTD Config 3.0 // EN" 
        "http://mybatis.org/dtd/mybatis config.dtd--3 " > 
< configuration > 
    
    <-! configuration external properties -> 
    < properties Resource =" datasource.properties "  /> 
    
    <-! Add log implemented -> 
    < Settings > 
        < Setting name =" logImpl " value =" LOG4J " /> 
        
        <-! whether to open an underscore and camel automatic conversion, http: // www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Auto-mapping -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
        
    
    <environments default="development">
        <environment id="development" >
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <mapper resource="com/ttx/example/mapper/UserMapper.xml"/>
        <mapper resource="com/ttx/example/mapper/UserResultMapper.xml"/>
        <mapper resource="com/ttx/example/mapper/DynamicSqlUserMapper.xml"/>
        <mapper resource="com/ttx/example/mapper/UserSqlProviderMapper.xml"/>
        <mapper resource="com/ttx/example/mapper/UserCacheMapper.xml"/>
    </mappers>
    
</configuration>

 

 

Two Dian SqlSessionFactoryBuilder # build () parsing configuration building SqlSessionFactory

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
// 委托给XMLConfigBuilder解析mybatis-config.xml XMLConfigBuilder parser
= new XMLConfigBuilder(inputStream, environment, properties);
    // 调用parser.parse()解析Configuration
return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } }

 

 

Wed and XMLConfigBuilder # the parse () parse xml configuration

  // 解析方法, 解析配置
  public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    parseConfiguration(parser.evalNode("/configuration"));  //根节点为configuration
    return configuration;
  }

 

 Private  void parseConfiguration (XNode the root) { 

    // parse the configuration process, a method to write code in a bit like a spring,
     // separated analytical method for the configuration element 
  // methods described herein correspond to the respective mybatis-config.xml child element
  // mybatis-config.xml the individual elements in the Configuration parsed into

the try { // Issue # 117 Read Properties First propertiesElement (root.evalNode ( "Properties" )); // Settings the Properties Settings settingsAsProperties = ( root.evalNode ( "Settings" )); // load the virtual file system loadCustomVfs (Settings); // load the log to achieve loadCustomLogImpl (Settings); // type alias typeAliasesElement (root.evalNode ( "typeAliases" )); // plugins pluginElement (root.evalNode ( "plugins" )); // object factory objectFactoryElement (root.evalNode ( "objectFactory" )); // objects packaging plants objectWrapperFactoryElement ( root.evalNode ( "objectWrapperFactory" )); // reflector factory reflectorFactoryElement (root.evalNode ( "reflectorFactory" )); // --------------------- --- // set Configuration attributes, // settings, typeAliases, plugins, the objectFactory, objectWrapperFactory, Configuration attributes corresponding to reflectorFactory settingsElement (Settings); // the Read the After objectFactory IT and objectWrapperFactory Issue # 631 // environment configuration environmentsElement (root.evalNode ( "Environments" )); // database the above mentioned id databaseIdProviderElement (root.evalNode ( "databaseIdProvider" )); // type of processor typeHandlerElement (root.evalNode ( "typeHandlers" )); // key // by mappers configuration path mapperElement (root.evalNode ( "by mappers" )); } the catch (Exception E) { the throw new new BuilderException ( "Error parsing the SQL Mapper Configuration Cause:. "+ And e);+ } }

 

 

Four Dian focuses on XMLConfigBuilder #mapperElement () parse mapper.xml, packed into mappedStatement

  // Load Mapper
   // ============================================ =
   // total inlet mybatis Mapper is loaded
   // 1. Find the corresponding interface to add a configuration package Mapper, mapper.xml profile should in the same package
   // 2. by configuring resource = "mapper.xml" load path 
   // ============================================= 
  Private  void mapperElement (XNode parent) throws Exception {   // by mappers 
    IF (parent =! null ) {
       for (XNode Child: parent.getChildren ()) { 

        IF ( "Package" .equals (child.getName ())) { // . 1. You can specify a "package" level
          Child.getStringAttribute mapperPackage = String ( "name" );
           // will load all classes package name, and use the annotation builder resolved to parse mapper.xml configuration file, and then parse mapper.class // only through specified xml configuration file to find, if the specified class, the corresponding profile and needs to be placed under a similar package, or the classpath path 
          configuration.addMappers (mapperPackage); 

        } the else {
             // single designated
             // Resource, specify the corresponding URL xml file, the class corresponding to the class specified 
          String Resource child.getStringAttribute = ( "Resource" ); 
          String URL = child.getStringAttribute ( "URL" ); 
          String mapperClass = child.getStringAttribute ( "class" );
           IF (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }

 

 

Five Dian XMLMapperBuilder # parse ()

  / * 
   * Main method, the parse 
   * / 
  public  void the parse () {
     IF (! Configuration.isResourceLoaded (Resource)) {
       // load mapper.xml respective analytical elements, including parsing Statement, The resultMap
       // warning in the MapperProxy MapperMethod package calls, call parameters will be transferred to the appropriate type, the corresponding data bindings 
      ConfigurationElement (parser.evalNode ( "/ Mapper" ));
       // set the parsed resource loaded 
      configuration.addLoadedResource (resource);
       // loading parsing corresponding mapper interface mapper interface into registry   
      bindMapperForNamespace (); 
    } 

    // load the analytical data have not yet been loaded 
    parsePendingResultMaps (); 
    parsePendingCacheRefs ();
    parsePendingStatements (); 
  }

 

  private void bindMapperForNamespace() {
    String namespace = builderAssistant.getCurrentNamespace();
    if (namespace != null) {
      Class<?> boundType = null;
      try {
        boundType = Resources.classForName(namespace);
      } catch (ClassNotFoundException e) {
        //ignore, bound type is not required
      }
      if (boundType != null) {
        if (!configuration.hasMapper(boundType)) {
          //May not know at The Real the Spring Resource name SO WE the SET A Flag
           // to Prevent loading Again from the this Resource at The Mapper interface
           // look AT MapperAnnotationBuilder # loadXmlResource 
          configuration.addLoadedResource ( "namespace:" + namespace);   // add is already in configuration resource loading 
          configuration.addMapper (boundType);   // add mapper interface configuration, then parse the added mapperRegistry 
        } 
      } 
    } 
  }

 

 

Six Dian will be added to the configuration of the mapper mapperRegistry, the period is resolved by mapperRegistry

  public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        // 添加进knownMappers, 值为对应的代理工厂(MapperProxyFactory)的类
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // It's important that the type is added before the parser is run
        //Automatically BE the Binding May at The otherwise by at The attempted Displays
         // Mapper Parser. the If at The of the type already Known IS, IT by Will not the try. 

        // use annotation builder to build, will first resolve mapper.xml configuration file, and then parse mapper.class annotation file 
        MapperAnnotationBuilder Parser = new new MapperAnnotationBuilder (config, type); 
        parser.parse (); 
        LoadCompleted = to true ; 
      } the finally {
         IF (! LoadCompleted) { 
          knownMappers.remove (type); 
        } 
      } 
    } 
  }

 

Guess you like

Origin www.cnblogs.com/timfruit/p/11462624.html