mybatis使用Resources和ClassLoaderWrapper读取配置文件

mybatis通过Resources读取配置文件(从类路径下加载资源)。Resources通过ClassLoaderWrapper(封装ClassLoader读取文件)进行文件加载。
首先看个mybatis中的例子:


  @BeforeClass
  public static void setup() throws Exception {
    createBlogDataSource();
    final String resource = "org/apache/ibatis/builder/MapperConfig.xml";
    //通过Resources加载配置文件
    final Reader reader = Resources.getResourceAsReader(resource);
    sqlMapper = new SqlSessionFactoryBuilder().build(reader);
  }

Resources提供的主要方法有:

//返回资源的url
getResourceURL(String resource)
getResourceURL(ClassLoader loader, String resource)
//读取资源作为stream返回
getResourceAsStream(String resource) 
getResourceAsStream(ClassLoader loader, String resource)
//读取资源作为Properties返回
getResourceAsProperties(String resource)
getResourceAsProperties(ClassLoader loader, String resource)
//读取资源作为Reader返回
getResourceAsReader(String resource)
getResourceAsReader(ClassLoader loader, String resource)
//读取资源作为File返回
getResourceAsFile(String resource)
getResourceAsFile(ClassLoader loader, String resource)
//从url中读取资源返回stream
getUrlAsStream(String urlString)
//从url中读取资源返回Reader
getUrlAsReader(String urlString)
//从url中读取资源返回Properties
getUrlAsProperties(String urlString)

Resources一般使用的场景:

  1. 从类路径加载 SQL Map 配置文件(如 sqlMap-config.xml)
  2. 从类路径加载 DaoMapper配置文件(如 dao.xml)
  3. 从类路径加载各种.properties 文件

Resources使用的几种方法:

  1. 对于简单的只读文本数据,加载为 Reader
  2. 对于简单的只读二进制或文本数据,加载为 Stream
  3. 对于可读写的二进制或文本文件,加载为 File
  4. 对于只读的配置属性文件,加载为 Properties
  5. 对于只读的通用资源,加载为 URL

在Resources中使用ClassLoaderWrapper加载文件,如:

 public static URL getResourceURL(ClassLoader loader, String resource) throws IOException {
    URL url = classLoaderWrapper.getResourceAsURL(resource, loader);
    if (url == null) {
      throw new IOException("Could not find resource " + resource);
    }
    return url;
  }

在ClassLoaderWrapper中对应的代码为:

public URL getResourceAsURL(String resource, ClassLoader classLoader) {
    return getResourceAsURL(resource, getClassLoaders(classLoader));
  }
 
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
    return new ClassLoader[]{
    	//参数指定的类加载器
        classLoader,
        // 系统指定的默认加载器
        defaultClassLoader,
        //当前线程绑定的类加载器
        Thread.currentThread().getContextClassLoader(),
        // 当前类使用的类加载器
        getClass().getClassLoader(),
        // System ClassLoader(App ClassLoader)
        systemClassLoader};
  }
 
  
  URL getResourceAsURL(String resource, ClassLoader[] classLoader) {
    URL url;
    //循环ClassLoader,通过指定或者默认的ClassLoader读取文件
    for (ClassLoader cl : classLoader) {
      if (null != cl) {
        // look for the resource as passed in...
        url = cl.getResource(resource);
        // 如果在resource的路径下没有找到,加“/”再进行查询读取
        if (null == url) {
          url = cl.getResource("/" + resource);
        }
        // 如果查询到url,终止循环返回结果
        if (null != url) {
          return url;
        }
      }
    }
    return null;

  }

ClassLoaderWrapper提供的主要方法有:

getResourceAsURL(String resource)
getResourceAsURL(String resource, ClassLoader classLoader)
getResourceAsStream(String resource)
getResourceAsStream(String resource, ClassLoader classLoader)
classForName(String name)
classForName(String name, ClassLoader classLoader)

其中getResourceAsURL的源码已粘贴在上面,下面再粘贴下getResourceAsStream和classForName的源码:

InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
   //循环ClassLoader 数组
    for (ClassLoader cl : classLoader) {
      if (null != cl) {
        // 根据入参resource,读取该路径下文件
        InputStream returnValue = cl.getResourceAsStream(resource);
        // 如果没有,加上“/”再尝试读取
        if (null == returnValue) {
          returnValue = cl.getResourceAsStream("/" + resource);
        }
		//如果读取到,终止循环,返回结果
        if (null != returnValue) {
          return returnValue;
        }
      }
    }
    return null;
  }
Class classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {
    for (ClassLoader cl : classLoader) {
      if (null != cl) {
        try {
          Class c = Class.forName(name, true, cl);
          if (null != c) {
            return c;
          }
        } catch (ClassNotFoundException e) {
          // we'll ignore this until all classloaders fail to locate the class
        }
      }
    }
    throw new ClassNotFoundException("Cannot find class: " + name);
  }

你可能感兴趣的:(mybatis,MyBatis源码解析)