最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java資源加載機制及使用最佳實踐

 更新時間:2025年12月13日 09:15:18   作者:lang20150928  
Java類加載器的資源加載機制,包括`getResource`、`getResources`、`findResource`、`findResources`等方法,本文給大家介紹Java資源加載機制及使用最佳實踐,感興趣的朋友跟隨小編一起看看吧
    /**
     * Finds the resource with the given name.  A resource is some data
     * (images, audio, text, etc) that can be accessed by class code in a way
     * that is independent of the location of the code.
     *
     * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
     * identifies the resource.
     *
     * <p> This method will first search the parent class loader for the
     * resource; if the parent is <tt>null</tt> the path of the class loader
     * built-in to the virtual machine is searched.  That failing, this method
     * will invoke {@link #findResource(String)} to find the resource.  </p>
     *
     * @apiNote When overriding this method it is recommended that an
     * implementation ensures that any delegation is consistent with the {@link
     * #getResources(java.lang.String) getResources(String)} method.
     *
     * @param  name
     *         The resource name
     *
     * @return  A <tt>URL</tt> object for reading the resource, or
     *          <tt>null</tt> 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;
    }
    /**
     * Finds all the resources with the given name. A resource is some data
     * (images, audio, text, etc) that can be accessed by class code in a way
     * that is independent of the location of the code.
     *
     * <p>The name of a resource is a <tt>/</tt>-separated path name that
     * identifies the resource.
     *
     * <p> The search order is described in the documentation for {@link
     * #getResource(String)}.  </p>
     *
     * @apiNote When overriding this method it is recommended that an
     * implementation ensures that any delegation is consistent with the {@link
     * #getResource(java.lang.String) getResource(String)} method. This should
     * ensure that the first element returned by the Enumeration's
     * {@code nextElement} method is the same resource that the
     * {@code getResource(String)} method would return.
     *
     * @param  name
     *         The resource name
     *
     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
     *          the resource.  If no resources could  be found, the enumeration
     *          will be empty.  Resources that the class loader doesn't have
     *          access to will not be in the enumeration.
     *
     * @throws  IOException
     *          If I/O errors occur
     *
     * @see  #findResources(String)
     *
     * @since  1.2
     */
    public Enumeration<URL> getResources(String name) throws IOException {
        @SuppressWarnings("unchecked")
        Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
        if (parent != null) {
            tmp[0] = parent.getResources(name);
        } else {
            tmp[0] = getBootstrapResources(name);
        }
        tmp[1] = findResources(name);
        return new CompoundEnumeration<>(tmp);
    }
    /**
     * Finds the resource with the given name. Class loader implementations
     * should override this method to specify where to find resources.
     *
     * @param  name
     *         The resource name
     *
     * @return  A <tt>URL</tt> object for reading the resource, or
     *          <tt>null</tt> if the resource could not be found
     *
     * @since  1.2
     */
    protected URL findResource(String name) {
        return null;
    }
    /**
     * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
     * representing all the resources with the given name. Class loader
     * implementations should override this method to specify where to load
     * resources from.
     *
     * @param  name
     *         The resource name
     *
     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
     *          the resources
     *
     * @throws  IOException
     *          If I/O errors occur
     *
     * @since  1.2
     */
    protected Enumeration<URL> findResources(String name) throws IOException {
        return java.util.Collections.emptyEnumeration();
    }
    /**
     * Registers the caller as parallel capable.
     * The registration succeeds if and only if all of the following
     * conditions are met:
     * <ol>
     * <li> no instance of the caller has been created</li>
     * <li> all of the super classes (except class Object) of the caller are
     * registered as parallel capable</li>
     * </ol>
     * <p>Note that once a class loader is registered as parallel capable, there
     * is no way to change it back.</p>
     *
     * @return  true if the caller is successfully registered as
     *          parallel capable and false if otherwise.
     *
     * @since   1.7
     */
    @CallerSensitive
    protected static boolean registerAsParallelCapable() {
        Class<? extends ClassLoader> callerClass =
            Reflection.getCallerClass().asSubclass(ClassLoader.class);
        return ParallelLoaders.register(callerClass);
    }
    /**
     * Find a resource of the specified name from the search path used to load
     * classes.  This method locates the resource through the system class
     * loader (see {@link #getSystemClassLoader()}).
     *
     * @param  name
     *         The resource name
     *
     * @return  A {@link java.net.URL <tt>URL</tt>} object for reading the
     *          resource, or <tt>null</tt> if the resource could not be found
     *
     * @since  1.1
     */
    public static URL getSystemResource(String name) {
        ClassLoader system = getSystemClassLoader();
        if (system == null) {
            return getBootstrapResource(name);
        }
        return system.getResource(name);
    }
    /**
     * Finds all resources of the specified name from the search path used to
     * load classes.  The resources thus found are returned as an
     * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
     * java.net.URL <tt>URL</tt>} objects.
     *
     * <p> The search order is described in the documentation for {@link
     * #getSystemResource(String)}.  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  An enumeration of resource {@link java.net.URL <tt>URL</tt>}
     *          objects
     *
     * @throws  IOException
     *          If I/O errors occur
     * @since  1.2
     */
    public static Enumeration<URL> getSystemResources(String name)
        throws IOException
    {
        ClassLoader system = getSystemClassLoader();
        if (system == null) {
            return getBootstrapResources(name);
        }
        return system.getResources(name);
    }
    /**
     * Find resources from the VM's built-in classloader.
     */
    private static URL getBootstrapResource(String name) {
        URLClassPath ucp = getBootstrapClassPath();
        Resource res = ucp.getResource(name);
        return res != null ? res.getURL() : null;
    }
    /**
     * Find resources from the VM's built-in classloader.
     */
    private static Enumeration<URL> getBootstrapResources(String name)
        throws IOException
    {
        final Enumeration<Resource> e =
            getBootstrapClassPath().getResources(name);
        return new Enumeration<URL> () {
            public URL nextElement() {
                return e.nextElement().getURL();
            }
            public boolean hasMoreElements() {
                return e.hasMoreElements();
            }
        };
    }
    // Returns the URLClassPath that is used for finding system resources.
    static URLClassPath getBootstrapClassPath() {
        return sun.misc.Launcher.getBootstrapClassPath();
    }
    /**
     * Returns an input stream for reading the specified resource.
     *
     * <p> The search order is described in the documentation for {@link
     * #getResource(String)}.  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  An input stream for reading the resource, or <tt>null</tt>
     *          if the resource could not be found
     *
     * @since  1.1
     */
    public InputStream getResourceAsStream(String name) {
        URL url = getResource(name);
        try {
            return url != null ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }
    /**
     * Open for reading, a resource of the specified name from the search path
     * used to load classes.  This method locates the resource through the
     * system class loader (see {@link #getSystemClassLoader()}).
     *
     * @param  name
     *         The resource name
     *
     * @return  An input stream for reading the resource, or <tt>null</tt>
     *          if the resource could not be found
     *
     * @since  1.1
     */
    public static InputStream getSystemResourceAsStream(String name) {
        URL url = getSystemResource(name);
        try {
            return url != null ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }

以上代碼是 Java 標準庫中 java.lang.ClassLoader 類的一部分,主要涉及 資源(resource)加載機制。理解這些方法對深入掌握 Java 類加載機制、模塊化系統(tǒng)、以及框架(如 Spring、Hibernate、MyBatis 等)如何加載配置文件、模板、靜態(tài)資源等至關重要。

一、核心概念:什么是“Resource”?

在 Java 中,Resource 是指與類代碼邏輯相關的非代碼數(shù)據(jù),例如:

  • 配置文件(如 application.properties
  • XML 映射文件(如 MyBatis 的 mapper.xml
  • 圖片、音頻、文本等靜態(tài)資源
  • 國際化語言包(.properties

這些資源通常和 .class 文件一起打包在 JAR/WAR 中,或者放在 classpath 目錄下。

? 關鍵點:Resource 的路徑是相對于 classpath 根目錄 的,用 / 分隔(不是平臺相關的 \/)。

二、核心方法解析

1.public URL getResource(String name)

功能:

根據(jù)資源名(如 "config/app.properties")返回一個 URL,可用于讀取該資源。

搜索順序(雙親委派模型):

  1. 先委托 父類加載器(parent ClassLoader)查找;
  2. 如果父加載器為 null(即啟動類加載器 Bootstrap ClassLoader),則調用 getBootstrapResource();
  3. 若仍未找到,則調用子類可重寫的 findResource(name) 方法(由當前 ClassLoader 自己查找)。

?? 這體現(xiàn)了 雙親委派模型(Parent Delegation Model),保證核心資源優(yōu)先由上級加載器處理,避免重復或沖突。

返回值:

  • 成功:URL 對象(如 jar:file:/xxx.jar!/config/app.properties
  • 失?。?code>null

2.public Enumeration<URL> getResources(String name)

功能:

返回所有匹配名稱的資源(可能有多個同名資源分布在不同 JAR 或目錄中)。

使用場景:

  • SPI(Service Provider Interface)機制:如 META-INF/services/javax.servlet.ServletContainerInitializer
  • 多模塊項目中合并多個 application.properties

注意:

  • 返回的是 Enumeration<URL>,需遍歷。
  • 第一個元素應與 getResource() 返回結果一致(API 注釋強調一致性)。

3.protected URL findResource(String name)和protected Enumeration<URL> findResources(String name)

作用:

這兩個是 模板方法,供自定義 ClassLoader 子類實現(xiàn)具體資源查找邏輯。

  • 默認實現(xiàn):findResource 返回 null,findResources 返回空枚舉。
  • 實際實現(xiàn)如 URLClassLoader 會從指定的 URL 路徑(如 JAR、目錄)中查找資源。

4. 靜態(tài)方法:getSystemResource/getSystemResources/getSystemResourceAsStream

功能:

通過 系統(tǒng)類加載器(System ClassLoader) 加載資源,等價于:

ClassLoader.getSystemClassLoader().getResource(name);

?? 系統(tǒng)類加載器通常是 AppClassLoader(應用類加載器),負責加載 -classpath 指定的類和資源。

使用場景:

  • 工具類中直接讀取 classpath 資源(不依賴當前類的 ClassLoader)
  • 啟動時加載全局配置

5.getResourceAsStream(String name)

功能:

直接返回 InputStream,省去手動 openStream() 的步驟。

內部實現(xiàn):

URL url = getResource(name);
return url != null ? url.openStream() : null;

?? 注意:如果資源不存在或 I/O 出錯,返回 null(不會拋異常?。?/p>

三、常見使用方式示例

1. 從當前類的 ClassLoader 讀取資源

InputStream is = MyClass.class.getClassLoader().getResourceAsStream("config/db.properties");

2. 從當前類所在包的相對路徑讀取(注意開頭無/)

// 假設 MyClass 在 com.example 包下
InputStream is = MyClass.class.getResourceAsStream("local-config.txt"); 
// 實際路徑:com/example/local-config.txt

?? Class.getResource()ClassLoader.getResource() 的區(qū)別:

  • Class.getResource(path)
    • path/ 開頭 → 從 classpath 根開始
    • 否則 → 從當前類所在包開始
  • ClassLoader.getResource(path)始終從 classpath 根開始

四、在主流框架中的應用

1.Spring Framework

  • ResourceLoader 接口抽象了資源加載,底層大量使用 ClassLoader.getResource()
  • @PropertySource("classpath:app.properties") → 通過 ClassLoader 查找。
  • ApplicationContext 啟動時掃描 META-INF/spring.factories(使用 getResources() 支持多 JAR 合并)。

2.MyBatis

  • Mapper XML 文件通常通過:
    InputStream is = Resources.getResourceAsStream("mappers/UserMapper.xml");
    
    其中 Resources 工具類內部調用 ClassLoader.getResourceAsStream()。

3.Hibernate / JPA

  • persistence.xml 必須位于 META-INF/persistence.xml,由 PersistenceProvider 通過 ClassLoader.getResources("META-INF/persistence.xml") 發(fā)現(xiàn)。

4.SPI 機制(Java ServiceLoader)

  • ServiceLoader.load(MyService.class) 會調用:
    classloader.getResources("META-INF/services/com.example.MyService");
    
    從而發(fā)現(xiàn)所有 JAR 中提供的實現(xiàn)。

五、注意事項 & 最佳實踐

問題建議
資源路徑錯誤使用 / 分隔,不要用 \;確認是否從 classpath 根開始
打包后資源找不到確保構建工具(Maven/Gradle)將資源復制到 target/classes
多個同名資源使用 getResources() 遍歷,避免只取第一個導致遺漏
安全管理器限制在受限環(huán)境(如 Applet)中可能返回 null
流未關閉使用 try-with-resources 確保 InputStream 關閉

六、總結

方法用途是否靜態(tài)委托父加載器
getResource()獲取單個資源 URL?
getResources()獲取所有同名資源?
getSystemResource()通過系統(tǒng)類加載器獲取??(直接用系統(tǒng)加載器)
getResourceAsStream()直接獲取輸入流?
findResource()子類實現(xiàn)具體查找邏輯?(自身實現(xiàn))

?? 核心思想:Java 的資源加載機制基于 ClassLoader 的雙親委派模型,保證了資源查找的安全性、一致性和可擴展性。理解它,就掌握了 Java 應用加載配置、插件、靜態(tài)文件的底層邏輯。

如果你正在開發(fā)自定義 ClassLoader、模塊化系統(tǒng)、或需要動態(tài)加載資源(如熱部署、插件系統(tǒng)),這些方法就是你的基石。需要我進一步舉例說明如何自定義 ClassLoader 實現(xiàn)資源加載嗎?

到此這篇關于Java資源加載機制及使用最佳實踐的文章就介紹到這了,更多相關java資源加載機制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

光泽县| 灵川县| 宝丰县| 嘉荫县| 叶城县| 美姑县| 晴隆县| 门源| 沂水县| 五峰| 盘锦市| 通榆县| 阿城市| 临泽县| 枣强县| 息烽县| 壤塘县| 云梦县| 青冈县| 大足县| 巴林左旗| 吴川市| 溧阳市| 奎屯市| 曲松县| 确山县| 翁牛特旗| 巴南区| 四平市| 北流市| 台湾省| 辽宁省| 柞水县| 贵溪市| 全州县| 区。| 图片| 龙口市| 惠水县| 横山县| 普宁市|