getResource()和getSystemResource()分析
1. getClass().getResource()
第一步,
getClass().getResource(path)
是有一个路径参数的,这个路径会先被转换成"类所在的包名称+path",举个例子,当调用com.test.A.class.getResource(“config.properties”)
时,最终这个path会被转换为"com\test\config.properties"。
第二步,便会调用类的类加载器对象的getResource()方法,继续上面的例子,也就是等于:
com.test.A.class.getClassLoader().getResource("com\test\config.properties")
(为了方便A类的类加载其对象简称cl)。
第三步,分析
cl.getResource()
发现,此方法会返回cl的"第一条匹配到记录的加载路径+path"的URL对象。举个例子,cl类加载器的加载路径是"\home\aaa"和"\home\bbb",而config.properties在\home\bbb下面,那么cl.getResource("com\test\config.properties")
返回的URL就是"\home\bbb\com\test\config.properties",注意,这个寻找的过程也是符合双亲委托机制的。如果父类的加载路径中存在匹配项,那么返回的便是父类中的匹配路径。(此方法中核心部分是要被子类来覆盖的,所以此处说的是URLClassLoader中的实现)
2. ClssLoader.getSystemResource()
ClssLoader.getSystemResource(path)
更简单,它等价getSystemClassLoader().getResource(path)
,衔接上面的第三步。
3. 总结
也就是说,不管是类对象的getResource()还是类加载器的getSystemResouce(),都是走的类加载器的getResource(),类加载器会搜索自己的加载路径来匹配寻找项。而最常用的类加载器就是AppClassLoader,又因为APPClassLoader的加载路径是classpath,所以网上文章一般都会说getClass().getResouce()是返回classpath,这是不够准确的。