栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中配置文件加载的方法与原理剖析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中配置文件加载的方法与原理剖析

类加载器ClassLoader:

  1. 启动类加载器: Bootstrap ClassLoader Load classes from JRE/lib/rt.jar 不是用Java代码编写, 程序中获取不到, 因此无法通过ClassLoader获取这个目录下的Resource File
  2. 扩展类加载器: Extension ClassLoader Load classes from JRE/lib/ext or Djava.ext.dirs Java代码中可以获取的最父级ClassLoader
  3. 系统类加载器: AppClassLoader Load classes from classPath or Djava.class.path
  4. 用户类加载器: User-Defined ClassLoader

TIP: 查找类或者查找文件时, 是从一个类加载器A开始找Parent ClassLoader, 一直找到Extension ClassLoader,
然后执行getBootstrapResource(String)方法从BootstrapClassPath加载Resource File, 如果加载到了直接返回,
否则从Extension ClassLoader回溯至A ClassLoader(双亲委派):

  1. 调用getLookupCache(String)方法找出之前查找过的Loader(ClassPath)的下标

  2. 调用getNextLoader(int[], int)方法找出下一个需要查找Resource File的Loader(ClassPath),

    2.1 如果缓存的Loader(ClassPath)的下标数组为null, 则调用getLoader(int)方法从当前ClassLoader的Stack urls中获取一个URL — 栈.pop(), 这个栈保存的是Loader(ClassPath)的URL, 再通过URL获取其Loader(ClassPath)并返回 — 查找过的就放进缓存: ArrayList loaders

    2.2 如果缓存的Loader(ClassPath)的下标数组不为null, 则通过下标从ArrayList loaders中取出Loader(ClassPath)返回

  3. 获取到Loader(ClassPath)后, 调用URLClassPath.Loader.findResource(String, boolean)方法查找该Loader(ClassPath)下的Resource File的URL

    3.1 以该Loader(ClassPath)的ClassPath为基路径, 用户输入的要查找的路径为子路径, 构造一个URL, 如果findResource(String, boolean)的第二个参数为true, 那么将会进行路径合法性的检查: URLClassPath.check(URL);

    3.2 对URL指向HTTP Resource的, setRequestMethod(“HEAD”), 并检查ResponseCode, 如果大于等于400, 说明找不到HTTP Resource, 直接返回null

    3.3 对URL指向其他Resource的, 设置缓存标志为false

    3.4 返回Resource File的URL

  4. URL.openStream();

TIP: ClassPath是相对于ClassLoader来说的, 因此每个ClassLoader都有自己的ClassPath, 我们通常说的ClassPath是指AppClassLoader的ClassPath

获取ClassLoader:

  1. BootstrapClassLoader: null
    String.class.getClassLoader();
    ClassLoader.getSystemClassLoader().getParent().getParent();

  2. ExtClassLoader:
    Bootstrap.class.getClassLoader();
    ClassLoader.getSystemClassLoader().getParent();

  3. AppClassLoader:
    ClassLoader.getSystemClassLoader();
    JavaSE场景下: Thread.currentThread().getContextClassLoader();
    JavaSE场景下: this.getClass().getClassLoader();

  4. ParallelWebappClassLoader:
    JavaEE场景下: Thread.currentThread().getContextClassLoader();
    JavaEE场景下: this.getClass().getClassLoader();

  5. CustomClassLoader:

ClassPath路径(打包后):

  1. 常见工程: classes/
  2. Web工程: /WEB-INF/classes/
  3. 普通Java工程: ApplicationName目录下(ApplicationName/)

读取文件流例子:

  1. 从AppClassLoader开始找((JRE/lib/ext or java.ext.dirs) + (classPath or Djava.class.path)):
    ClassLoader.getSystemResourceAsStream();
    JavaSE场景下: Thread.currentThread().getContextClassLoader().getResourceAsStream();
    JavaSE场景下: this.getClass().getClassLoader().getResourceAsStream();

  2. 从AppClassLoader开始找(封装后的):
    this.getClass().getResourceAsStream(); : 不以/开头时,在此类所在的包下获取资源, 以/开头时, 在ClassPath路径下获取资源

  3. 从ParallelWebappClassLoader开始找:
    JavaEE场景下: Thread.currentThread().getContextClassLoader().getResourceAsStream();
    JavaEE场景下: this.getClass().getClassLoader().getResourceAsStream();

  4. 从WebApp根目录下开始找:
    在Servlet中: this.getServletContext().getResourceAsStream();

  5. MyBatis的工具: Resources.getResourceAsStream();

  6. 无法获取查找路径之外的资源: Method threw ‘java.lang.IllegalArgumentException’ exception.
    The resource path […] has been normalized to [null] which is not valid

  7. ResourceBundle.getBundle(String baseName, Locale locale);

TIP:

  1. ServletContext: Servlet应用上下文, 可以研究一下
  2. ClassLoader.getBootstrapClassPath(); 获取Bootstrap ClassLoader所加载的Resource File的路径
  3. 找不到路径时, 就用ClassLoader.getResource("")方法调试,或用ClassLoader.getResourceAsStream(“meta-INF”);或this.getClass().getResource("/");
  4. System.getProperty(“user.dir”); 和上述问题无关, 是JVM启动时指定的属性
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643021.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号