Class.getResourceAsStream 和 ClassLoder.getResourceAsStream 的区别

问题描述

最近学习MyBaits时用到了 InputStream Resources.getResourceAsStream(String resource)来读取MyBatis配置文件,为了方便使用,封装了一个SqlSessionFactoryUtil,代码如下

并且将这个类放在了一个单独的jar包中,其他工程会引用这个jar包,当然其他工程的MyBatis配置文件名称均为Mybatis-Configuration.xml

问题就是,测试时报错,无法找到Mybatis-Configuration.xml文件,但工程中这个文件确实存在,如图

 

package canger.study.Utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Administrator on 2018\2\12 0012.
 */
public class SqlSessionFactoryUtil {
    private static String resource = "Mybatis-Configuration.xml";
    private static SqlSessionFactory sqlSessionFactory = null;
    public static void setResourcePath(String path){
        resource = path;
    }
    private static void initSqlSessionFactory() throws IOException {
        if (sqlSessionFactory!=null){
            return;
        }

        synchronized (SqlSessionFactoryUtil.class){
            if(sqlSessionFactory==null){
                InputStream resourceAsStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            }
        }
    }

    public static SqlSession openSqlSession() throws IOException {
        initSqlSessionFactory();
        return sqlSessionFactory.openSession();
    }
}

 

问题排查

 InputStream Resources.getResourceAsStream(String resource)底层采用ClassLoder.getResourceAsStream(String resource)方法,ClassLoder.getResourceAsStream(String resource)调用时返回了null,百度后知道ClassLoder.getResourceAsStream(String resource)只会检查当前jar包的路径,不用检查其他jar包,所以无法找到文件,具体可参考 https://stackoverflow.com/questions/16570523/getresourceasstream-returns-null ,

同时Class..getResourceAsStream(String resource)会检查其他jar包,所以能够找到配置文件

修改后的代码如下

package canger.study.Utils;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
 * Created by Administrator on 2018\2\12 0012.
 */
public class SqlSessionFactoryUtil {
    private static String resource = "/Mybatis-Configuration.xml";
    private static SqlSessionFactory sqlSessionFactory = null;
    public static void setResourcePath(String path){
        resource = path;
    }
    private static void initSqlSessionFactory(){
        if (sqlSessionFactory!=null){
            return;
        }

        synchronized (SqlSessionFactoryUtil.class){
            if(sqlSessionFactory==null){
                InputStream resourceAsStream = SqlSessionFactoryUtil.class.getClassLoader().getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
            }
        }
    }

    public static SqlSession openSqlSession(){
        initSqlSessionFactory();
        return sqlSessionFactory.openSession();
    }
}

总结

Class.getResourceAsStream(String name) 和 ClassLoader.getResourceAsStream(String name)区别如下

  1. ClassLoader.getResourceAsStream(String name)  无论name最前面是否为'/' 都会从classpath的根路径下查找

  2. Class.getResourceAsStream(String name)如果 name不以'/'开头则在当前类所在包的路径查找 ,如果name是以 '/' 开头的,那么就会从classpath的根路径下开始查找

  3. ClassLoader.getResourceAsStream(String name)不会查看其他jar包,Class.getResourceAsStream(String name)会查看其他jar包
posted @ 2018-02-12 22:02  canger  阅读(371)  评论(0编辑  收藏  举报