zoukankan      html  css  js  c++  java
  • mybatis 启动流程源码分析(一)

    Mybatis 启动流程

    @Before
        public void init() throws IOException {
            String resouce = "mybatis-config.xml";
            /**
             * 读取 mybatis文件,返回的是 InputStream流
             */
            InputStream inputStream = Resources.getResourceAsStream(resouce);
            /**
             * 使用 SqlSessionFactoryBuilder 来构建出一个 SqlSessionFactory来.
             */
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            session = sqlSessionFactory.openSession();
    
        }
    
    1. 通过Resouces提供的getResourceAsStream,加载mybatis-config.xml 文件,从下面的源码中可以看到,不仅可以读取转为InputStream,还可以返回Reader,Properties
    /**
     * A class to simplify access to resources through the classloader.
     *
     * @author Clinton Begin
     */
    public class Resources {
    
        private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();
    
      /*
       * Returns a resource on the classpath as a Stream object
       *
       * @param resource The resource to find
       * @return The resource
       * @throws java.io.IOException If the resource cannot be found or read
       */
      public static InputStream getResourceAsStream(String resource) throws IOException {
        return getResourceAsStream(null, resource);
      }
    
      /*
       * Returns a resource on the classpath as a Stream object
       *
       * @param loader   The classloader used to fetch the resource
       * @param resource The resource to find
       * @return The resource
       * @throws java.io.IOException If the resource cannot be found or read
       */
      public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
        InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
        if (in == null) {
          throw new IOException("Could not find resource " + resource);
        }
        return in;
      }
    
      /*
       * Returns a resource on the classpath as a Properties object
       *
       * @param resource The resource to find
       * @return The resource
       * @throws java.io.IOException If the resource cannot be found or read
       */
      public static Properties getResourceAsProperties(String resource) throws IOException {
        Properties props = new Properties();
        InputStream in = getResourceAsStream(resource);
        props.load(in);
        in.close();
        return props;
      }
    
      /*
       * Returns a resource on the classpath as a Properties object
       *
       * @param loader   The classloader used to fetch the resource
       * @param resource The resource to find
       * @return The resource
       * @throws java.io.IOException If the resource cannot be found or read
       */
      public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException {
        Properties props = new Properties();
        InputStream in = getResourceAsStream(loader, resource);
        props.load(in);
        in.close();
        return props;
      }
    
      /*
       * Returns a resource on the classpath as a Reader object
       *
       * @param resource The resource to find
       * @return The resource
       * @throws java.io.IOException If the resource cannot be found or read
       */
      public static Reader getResourceAsReader(String resource) throws IOException {
        Reader reader;
        if (charset == null) {
          reader = new InputStreamReader(getResourceAsStream(resource));
        } else {
          reader = new InputStreamReader(getResourceAsStream(resource), charset);
        }
        return reader;
      }
    
      /*
       * Returns a resource on the classpath as a Reader object
       *
       * @param loader   The classloader used to fetch the resource
       * @param resource The resource to find
       * @return The resource
       * @throws java.io.IOException If the resource cannot be found or read
       */
      public static Reader getResourceAsReader(ClassLoader loader, String resource) throws IOException {
        Reader reader;
        if (charset == null) {
          reader = new InputStreamReader(getResourceAsStream(loader, resource));
        } else {
          reader = new InputStreamReader(getResourceAsStream(loader, resource), charset);
        }
        return reader;
      }
    
    }
    
    1. new SqlSessionFactoryBuilder().build() 读取文件流,并解析,其中提供了包含Reader和InputStream的重载方法,于Resources中提供的方法相对应。
     public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
          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.
          }
        }
      }
    // 这次我使用的是该方法,传入的是inputStream.
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
          //new XMLConfigBuilder()构造方法,
          XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
          // 重点:使用XMLConfigBuilder的parse方法,去解析xml配置文件
          return build(parser.parse());
        } catch (Exception e) {
          throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
          ErrorContext.instance().reset();
          try {
            inputStream.close();
          } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
          }
        }
      }
    
      public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
      }
    
    1. 使用XMLConfigBuilder构造方法构建对象,
     public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
        //XMLMapperEntityResolver mybatis的实体解析器
        this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
      }
      private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
        super(new Configuration());
        ErrorContext.instance().resource("SQL Mapper Configuration");
        this.configuration.setVariables(props);
        this.parsed = false;
        this.environment = environment;
        this.parser = parser;
      }
    // 解析xml 配置文件,返回一个configuration对象,从这儿可以看出,加载的配置内容都是存放在Configuration对象中。
     public Configuration parse() {
        if (parsed) {
          throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        }
        parsed = true;
        // parser.evalNode("/configuration")
        parseConfiguration(parser.evalNode("/configuration"));
        return configuration;
      }
    // 这部分是解析xml文件中的每个节点配置,之后单独再分析
    private void parseConfiguration(XNode root) {
        try {
          //issue #117 read properties first
          propertiesElement(root.evalNode("properties"));
          Properties settings = settingsAsProperties(root.evalNode("settings"));
          loadCustomVfs(settings);
          typeAliasesElement(root.evalNode("typeAliases"));
          pluginElement(root.evalNode("plugins"));
          objectFactoryElement(root.evalNode("objectFactory"));
          objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
          reflectorFactoryElement(root.evalNode("reflectorFactory"));
          settingsElement(settings);
          // read it after objectFactory and objectWrapperFactory issue #631
          environmentsElement(root.evalNode("environments"));
          databaseIdProviderElement(root.evalNode("databaseIdProvider"));
          typeHandlerElement(root.evalNode("typeHandlers"));
          mapperElement(root.evalNode("mappers"));
        } catch (Exception e) {
          throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
        }
      }
    
    

    4.创建XPathParser解析器来解析Xml文件。

    public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
        commonConstructor(validation, variables, entityResolver);
        this.document = createDocument(new InputSource(inputStream));
      }
    
    // 给属性赋值,获取xpath对象
      private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
        this.validation = validation;
        this.entityResolver = entityResolver;
        this.variables = variables;
        // 获取XpathFactory 类实例
        XPathFactory factory = XPathFactory.newInstance();
        // 使用factory创建XPathImpl对象
        this.xpath = factory.newXPath();
      }
    
    //使用Document解析器,返回Document对象
    private Document createDocument(InputSource inputSource) {
        // important: this must only be called AFTER common constructor
        try {
          // 创建DocumentBuilderFactoryImpl 实例
          DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
          factory.setValidating(validation);
    
          factory.setNamespaceAware(false);
          factory.setIgnoringComments(true);
          factory.setIgnoringElementContentWhitespace(false);
          factory.setCoalescing(false);
          factory.setExpandEntityReferences(true);
          // 使用工厂创建DocumentBuilder,再使用build去解析xml文件流
          DocumentBuilder builder = factory.newDocumentBuilder();
          builder.setEntityResolver(entityResolver);
          builder.setErrorHandler(new ErrorHandler() {
            @Override
            public void error(SAXParseException exception) throws SAXException {
              throw exception;
            }
    
            @Override
            public void fatalError(SAXParseException exception) throws SAXException {
              throw exception;
            }
    
            @Override
            public void warning(SAXParseException exception) throws SAXException {
            }
          });
          return builder.parse(inputSource);
        } catch (Exception e) {
          throw new BuilderException("Error creating document instance.  Cause: " + e, e);
        }
      }
    

    通过实现类DocumentBuilderImpl 解析文件流

    public Document parse(InputSource is) throws SAXException, IOException {
            if (is == null) {
                throw new IllegalArgumentException(
                    DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
                    "jaxp-null-input-source", null));
            }
            if (fSchemaValidator != null) {
                if (fSchemaValidationManager != null) {
                    fSchemaValidationManager.reset();
                    fUnparsedEntityHandler.reset();
                }
                resetSchemaValidator();
            }
            // 采用DomParser 解析器解析xml文件
            domParser.parse(is);
            Document doc = domParser.getDocument();
            domParser.dropDocumentReferences();
            return doc;
    
  • 相关阅读:
    Atitit s2018.6 s6 doc list on com pc.docx Atitit s2018.6 s6 doc list on com pc.docx  Aitit algo fix 算法系列补充.docx Atiitt 兼容性提示的艺术 attilax总结.docx Atitit 应用程序容器化总结 v2 s66.docx Atitit file cms api
    Atitit s2018.5 s5 doc list on com pc.docx  v2
    Atitit s2018.5 s5 doc list on com pc.docx  Acc 112237553.docx Acc baidu netdisk.docx Acc csdn 18821766710 attilax main num.docx Atiitt put post 工具 开发工具dev tool test.docx Atiitt 腾讯图像分类相册管家.docx
    Atitit s2018 s4 doc list dvchomepc dvccompc.docx .docx s2018 s4 doc compc dtS44 s2018 s4 doc dvcCompc dtS420 s2018 s4f doc homepc s2018 s4 doc compc dtS44(5 封私信 _ 44 条消息)WebSocket 有没有可能取代 AJAX
    Atitit s2018 s3 doc list alldvc.docx .docx s2018 s3f doc compc s2018 s3f doc homepc sum doc dvcCompc dtS312 s2018 s3f doc compcAtitit PathUtil 工具新特性新版本 v8 s312.docx s2018 s3f doc compcAtitit 操作日
    Atitit s2018.2 s2 doc list on home ntpc.docx  Atiitt uke制度体系 法律 法规 规章 条例 国王诏书.docx Atiitt 手写文字识别 讯飞科大 语音云.docx Atitit 代码托管与虚拟主机.docx Atitit 企业文化 每日心灵 鸡汤 值班 发布.docx Atitit 几大研发体系对比 Stage-Gat
    Atitit 文员招募规范 attilax总结
    Atitit r2017 r6 doc list on home ntpc.docx
    atitit r9 doc on home ntpc .docx
    Atitit.如何文章写好 论文 文章 如何写好论文 技术博客 v4
  • 原文地址:https://www.cnblogs.com/wanthune/p/13672360.html
Copyright © 2011-2022 走看看