本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《
阿里云开发者社区用户服务协议
》和
《
阿里云开发者社区知识产权保护指引
》。如果您发现本社区中有涉嫌抄袭的内容,填写
侵权投诉表单
进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
使用FileInputStream要传入File对象,此处便于演示,将输出配置文件的位置。
InputStream is = new FileInputStream(new File("ReflectDemo/resource/pro.properties"));
System.out.println(new File("ReflectDemo/resource/pro.properties").getPath());
ReflectDemo\resource\pro.properties
注:使用此方法获取获取配置文件要指定文件的绝对路径/相对路径。并且获取到的是在项目根目录下或盘符下的配置文件,对于出现在classpath(类路径)下的配置文件,FileInputStream是读不到的。
2.使用Class.getResourceAsStream()方法
此处便于演示,将调用Class.Resource().getPath()来输出文件位置
System.out.println(ReflectDemo.class.getResource("/pro.properties").getPath());
/D:/idea/object/out/production/ReflectDemo/pro.properties
此方法可以用于获取类路径的配置文件。
3.Class.getClassLoder().getResourceAsStream()方法
此处便于演示,将调用Class.getClassLoder().Resource().getPath()来输出文件位置
System.out.println(ReflectDemo.class.getClassLoader().getResource("pro.properties").getPath());
/D:/idea/object/out/production/ReflectDemo/pro.properties
以上两方法区别
Class.getResourceAsStream(String name) 其实调用的就是
Class.getClassLoder().getResourceAsStream(String name)。
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
return cl.getResourceAsStream(name);
调用之前多了一个用于解析name的操作,如果开头是“/”则跟直接调用Class.getClassLoder().getResourceAsStream(String path)一样
例:Class.getClassLoder().getResourceAsStream("");==Class.getResourceAsStream("/");
如果Class.getResourceAsStream(String name);开头不是"/",则Class.resolveName(name)方法将会返回此类文件的目录+name
也就是说此方法获取的Resource是在此类目录下的并非classpath根目录。
他们最终都会调用ClassLoder.getResource(String name);
这个方法通过递归实现,双亲委派原理。
* ...
* @param name
* The resource name
* @return A URL object for reading the resource, or
* null if the resource could not be found or the invoker
* doesn't have adequate privileges to get the resource.
* @since 1.1
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
if (url == null) {
url = findResource(name);
return url;
"该方法将首先在父类加载器中搜索资源; 如果父类加载器为null,则搜索虚拟机内置的类加载器的路径。 那个方法失败,将调用findResource(String)来查找资源。"
简单的说 就是第一次执行进去首先迭代进入最顶层的启动类加载器(Bootstrap ClassLoader)如果找不到资源,就会返回null ,并跳出去执行它子加载器(Extension ClassLoader)重写的findResource方法,如果返回null就继续跳出执行下一个子加载器(App ClassLoader)的findResoure方法,如果继续返回空的话(在没有自定义类加载器的情况下,就会直接返回 null。有的话,继续执行自定义类加载器的findResource方法)。这个方法会返回resource的URL对象 或者 nul。
对于喜欢"钻牛角尖"的小白,可能对于上面出现的 双亲委派,Bootstrap ClassLoader,Extension ClassLoader,App ClassLoader术语很困扰。请点击链接进行详细了解。
4.ClassLoader.getSystemResource()方法
相信眼睛尖的小伙伴已经发现了Class.getResourceAsStream()源代码中出现了这个方法。其实正如此方法所言,就是通过调用系统类加载器(App ClassLoader)的getResource()方法,和前两种方法没有什么本质上的区别。
1.一般不推荐通过FileInputStream 来获取资源文件
1.现在的web项目,resources编译后就在classes目录下,通过classloader可以直接获取
2.对于变动的环境(现在都是部署在linux机器上)来说不太适用。
2.class.getResource("/") == class.getClassLoader().getResource("")
其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。
3.Class.getResource真正调用ClassLoader.getResource方法之前,会先获取文件的路径(path不以'/'开头时,默认是从此类所在的包下取资源;path以'/'开头时,则是从项目的ClassPath根下获取资源)。
4.ClassLoader.getResource方法会通过双亲委派机制,先委派双亲去加载类,如果双亲没有加载到,则再由自己加载。
参考链接&进一步阅读
https://blog.csdn.net/zhangshk_/article/details/82704010
https://blog.csdn.net/eff666/article/details/52203406
物以类聚 人以群分
菅江晖
使用Java面向对象编写网络通信程序应用
Elasticsearch Java API Client 开发
手动部署Java Web环境(Alibaba Cloud Linux 2)
搭建Java Web开发环境(Anolis OS)