Mybatis源码分析:Resources
Mybatis IO处理工具Resources和ClassLoaderWrapper
Resources类位于org.apache.ibatis.io包下,用于处理相关的IO操作,例如将文件,网络资源进行读取并转换为File,InputStream,Reader,URL等Java类。Resources类提供了多个getResourceAsxxx()方法作为对外暴露的方法,Resources并不提供方法实现,而是内部维护着一个静态ClassLoaderWrapper实例,Resources中的方法都是通过调用ClassLoaderWrapper相关方法实现。下面列出了Resources最常用的方法。
方法名 | 参数 |
---|---|
File getResourceAsFile() | resource,classloader |
Properties getResourceAsProperties() | resource,classloader |
Reader getResourceAsReader() | resource,classloader |
InputStream getResourceAsStream() | resource,classloader |
URL getResourceURL() | resource,classloader |
Properties getUrlAsProperties() | resource,classloader |
setCharset() | Charset |
void setDefaultClassLoader(ClassLoader) | ClassLoader |
ClassLoaderWrapper
ClassLoaderWrapper并不提供public型构造器,所以无法直接进行实例化,只能通过上述的Resources类进行获取。该类提供了获取资源的两种方式,以InputStream形式读取本地资源,以URL形式读取本地资源。除此之外,ClassLoaderWrappe还提供了classForName()方法用于获取类路径对应的Class实例。下面是ClassLoaderWrapper提供的所有方法。可以看到,每种类型方法都提供了三种入参形式,其中一种方法需要提供一个ClassLoader数组,需要注意的是这种方法并不能直接调用,前两种方法都是交给带有classloader[]参数的方法进行实现的。如果不提供ClassLoader则设置为null。
- Class<?> classForName(String name)
- Class<?> classForName(String name, ClassLoader classLoader)
- Class<?> classForName(String name, ClassLoader[] classLoader)
- InputStream getResourceAsStream(String resource)
- InputStream getResourceAsStream(String resource, ClassLoader classLoader)
- InputStream getResourceAsStream(String resource, ClassLoader[] classLoader)
- URL getResourceAsURL(String resource)
- URL getResourceAsURL(String resource, ClassLoader classLoader)
- URL getResourceAsURL(String resource, ClassLoader[] classLoader)
- ClassLoader[] getClassLoaders(ClassLoader classLoader)
getClassLoaders()用于为getResouceAsxxx()方法提供多个加载器。前面说过,不传入加载器数组的方法都会调用 getResourceAsxxx(String resource, ClassLoader[] classLoader)相关的方法,而获取加载器数组的方式就是直接调用getClassLoaders()方法。
ClassLoader[] getClassLoaders(ClassLoader classLoader) { return new ClassLoader[]{ classLoader,//自定义加载器 defaultClassLoader, Thread.currentThread().getContextClassLoader(),//当前线程加载器 getClass().getClassLoader(),//类加载器 systemClassLoader//系统默认加载器 }; }
classForName()根据类路径生成Class实例,该方法的本质是调用classloader下的forname方法进行实例化的。
1 Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException { 2 for (ClassLoader cl : classLoader) { 3 if (null != cl) { 4 try { 5 Class<?> c = Class.forName(name, true, cl); 6 if (null != c) { 7 return c; 8 } 9 } catch (ClassNotFoundException e) { 10 // we'll ignore this until all classloaders fail to locate the class 11 } 12 } 13 } 14 throw new ClassNotFoundException("Cannot find class: " + name); 15 }
getResourceAsStream()和getResourceAsURL():这两个方法都是获取相关的资源,与File类不同的是,这两个方法传递的参数必须是相对路径,否则抛出异常。同classForName()一样,必须遍历classLoader数组,然后调用getResourceAsStream()和getResource()。
测试实例
1 package com.zzz.mybatis.io.service; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.Reader; 7 import java.net.URL; 8 import java.util.Properties; 9 import org.apache.ibatis.io.Resources; 10 import org.junit.Test; 11 public class ResourcesTest { 12 @Test 13 public void TestResources() throws IOException { 14 File f=new File("d:\\work\\workspace_redis\\mybatis\\src\\main\\resources\\mybatis-mysql.properties"); 15 System.out.println(f.exists()); 16 //自定义类加载器 17 ClassLoader classLoader = new ClassLoader() { 18 }; 19 InputStream inputStream= classLoader.getResourceAsStream("./mybatis-mysql.properties"); 20 File file=Resources.getResourceAsFile(classLoader,"./mybatis-mysql.properties"); 21 System.out.println(file.exists()); 22 Reader reader=Resources.getResourceAsReader(classLoader, "./mybatis-mysql.properties"); 23 Properties properties=Resources.getResourceAsProperties(classLoader, "./mybatis-mysql.properties"); 24 System.out.println(properties.keySet().toString()); 25 URL url=Resources.getResourceURL("./mybatis-mysql.properties"); 26 System.out.println(url.getContent().toString()); 27 } 28 }