其实mybatis框架,或者是说spring框架,都是从读取配置文件开始的,之后是各种操作,这种编程方式的有点就是,我们下载别人的jar包框架之后,修改一下配置文件就可以使用了,
这也是编码从硬编码到配置编码的过程演变,我们平常写代码的时候,也要注意从硬编码改成配置编码,其实有的时候配置编码都是被逼迫的,因为,老大总是要修改,没有办法,不可能每次都在自己机器上改好,然后上传服务器,没有那个闲工夫,如果使用配置文件,修改一下配置文件,保存就行了,就是这么的任性。
我们先从mybatis的获取资源的过程来说:首先,先不管mybatis怎么处理这个配置文件,但是第一步(虽然是面向对象编程,我一度被面向对象给迷惑了,以为面向对象就不是面向过程了,但是后来证明其实任何程序都是面向过程的,面向对象其实就是一种分析方法和分析思维而已,真是名字吓死人):读取资源无外乎就是获取流,只要我们能拿到流,我们就想操作就怎么操作,但是如何才能获取流,这是个问题,我们使用File的时候,总是出现,FileNotFoundException异常,这个异常就是找不到文件,有的时候文件明明就在那儿,但是还是获取不到,就是这么个郁闷的心情啊。mybatis就是使用ClassLoader获取资源的,为什么使用ClassLoader获取流,因为java有一个jvm:就是java的虚拟机,既然是虚拟机,就是安装在windows或者是linux上一个操作系统,jvm有自己寻找资源的方式,并且ClassLoader就是类加载器,他既然能加载class,class也是使用流的方式加载的,那么,就能加载我们的文件资源,道理都是一样子的。我们讲完了,看看mybatis的源码操作
org.apache.ibatis.io.
ClassLoaderWrapper
这个是mybatis包装的一个获取ClassLoader的包装类,其中只有三个方法值得我们去看,其他的都是重载:
第一个是:获取五种类类加载器(ClassLoader)的方法
/** * 获取多个ClassLoader,这一步是必须的,因为,我们就是从这个加载器中获取资源的流的 *五种类加载器:自己传入的、默认的类加载器、当前线程的类加载器、本类的类加载器、系统类加载器 * @param classLoader 我们定义的自己的类加载器 * @return 类加载器的数组 */ ClassLoader[] getClassLoaders(ClassLoader classLoader) { return new ClassLoader[]{ classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), systemClassLoader}; } 第二个方法是:记载资源为InputStream的形式输出
/** * 从一个ClassLoader中获取资源的流,这就是我们的目的 * * @param resource 资源的地址 * @param classLoader 类加载器 * @return 流 */ InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) { for (ClassLoader cl : classLoader) { if (null != cl) { // try to find the resource as passed InputStream returnValue = cl.getResourceAsStream(resource); // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource if (null == returnValue) { returnValue = cl.getResourceAsStream("/" + resource); } if (null != returnValue) { return returnValue; } } } return null; }
/* * Get a resource as a URL using the current class path * * @param resource - the resource to locate * @param classLoader - the class loaders to examine * @return the resource or null */ URL getResourceAsURL(String resource, ClassLoader[] classLoader) { URL url; for (ClassLoader cl : classLoader) { if (null != cl) { // look for the resource as passed in... url = cl.getResource(resource); // ...but some class loaders want this leading "/", so we'll add it // and try again if we didn't find the resource if (null == url) { url = cl.getResource("/" + resource); } // "It's always in the last place I look for it!" // ... because only an idiot would keep looking for it after finding it, so stop looking already. if (null != url) { return url; } } } // didn't find it anywhere. return null; }
/* * Attempt to load a class from a group of classloaders * * @param name - the class to load * @param classLoader - the group of classloaders to examine * @return the class * @throws ClassNotFoundException - Remember the wisdom of Judge Smails: Well, the world needs ditch diggers, too. */ 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); }