最新国产好看的视频,伊人天堂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 標(biāo)準(zhǔn)庫中 java.lang.ClassLoader 類的一部分,主要涉及 資源(resource)加載機制。理解這些方法對深入掌握 Java 類加載機制、模塊化系統(tǒng)、以及框架(如 Spring、Hibernate、MyBatis 等)如何加載配置文件、模板、靜態(tài)資源等至關(guān)重要。

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

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

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

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

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

二、核心方法解析

1.public URL getResource(String name)

功能:

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

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

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

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

返回值:

  • 成功: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>,需遍歷。
  • 第一個元素應(yīng)與 getResource() 返回結(jié)果一致(API 注釋強調(diào)一致性)。

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

作用:

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

  • 默認(rè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(應(yīng)用類加載器),負(fù)責(zé)加載 -classpath 指定的類和資源。

使用場景:

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

5.getResourceAsStream(String name)

功能:

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

內(nèi)部實現(xiàn):

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

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

三、常見使用方式示例

1. 從當(dāng)前類的 ClassLoader 讀取資源

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

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

// 假設(shè) 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 根開始
    • 否則 → 從當(dāng)前類所在包開始
  • ClassLoader.getResource(path)始終從 classpath 根開始

四、在主流框架中的應(yīng)用

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 工具類內(nèi)部調(diào)用 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) 會調(diào)用:
    classloader.getResources("META-INF/services/com.example.MyService");
    
    從而發(fā)現(xiàn)所有 JAR 中提供的實現(xiàn)。

五、注意事項 & 最佳實踐

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

六、總結(jié)

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

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

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

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

相關(guān)文章

  • Spring注解@Configuration和@Component區(qū)別詳解

    Spring注解@Configuration和@Component區(qū)別詳解

    @Component和@Configuration都可以作為配置類,之前一直都沒覺得這兩個用起來有什么差別,可能有時程序跑的和自己想的有所區(qū)別也沒注意到,下面這篇文章主要給大家介紹了關(guān)于Spring注解@Configuration和@Component區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Java中使用While語句自增運算遍歷數(shù)組典型實例

    Java中使用While語句自增運算遍歷數(shù)組典型實例

    這篇文章主要介紹了Java中使用While語句自增運算遍歷數(shù)組典型實例,本文直接給出實例代碼,并對每一句代碼都注解了詳細(xì)注釋,需要的朋友可以參考下
    2015-06-06
  • Java DWR內(nèi)存泄漏問題解決方案

    Java DWR內(nèi)存泄漏問題解決方案

    這篇文章主要介紹了Java DWR內(nèi)存泄漏問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-10-10
  • 搭建 springboot selenium 網(wǎng)頁文件轉(zhuǎn)圖片環(huán)境的詳細(xì)教程

    搭建 springboot selenium 網(wǎng)頁文件轉(zhuǎn)圖片環(huán)境的詳細(xì)教程

    這篇文章主要介紹了搭建 springboot selenium 網(wǎng)頁文件轉(zhuǎn)圖片環(huán)境,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Spring Bean生命周期之BeanDefinition的合并過程詳解

    Spring Bean生命周期之BeanDefinition的合并過程詳解

    這篇文章主要為大家詳細(xì)介紹了Spring Bean生命周期之BeanDefinition的合并過程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

    2022-03-03
  • 詳解elasticsearch之metric聚合實現(xiàn)示例

    詳解elasticsearch之metric聚合實現(xiàn)示例

    這篇文章主要為大家介紹了elasticsearch之metric聚合實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Mybatis-Plus實現(xiàn)用戶ID自增出現(xiàn)的問題解決

    Mybatis-Plus實現(xiàn)用戶ID自增出現(xiàn)的問題解決

    項目基于 SpringBoot + MybatisPlus 3.5.2 使用數(shù)據(jù)庫自增ID時, 出現(xiàn)重復(fù)鍵的問題,本文就來介紹一下解決方法,感興趣的可以了解一下
    2023-09-09
  • 探究Android系統(tǒng)中解析JSON數(shù)據(jù)的方式

    探究Android系統(tǒng)中解析JSON數(shù)據(jù)的方式

    這篇文章主要介紹了探究Android系統(tǒng)中解析JSON數(shù)據(jù)的方式,文中講到了使用Java代碼實現(xiàn)的處理JSON的一些主要方法,需要的朋友可以參考下
    2015-07-07
  • idea編寫yml、yaml文件以及其優(yōu)先級的使用

    idea編寫yml、yaml文件以及其優(yōu)先級的使用

    本文主要介紹了idea編寫yml、yaml文件以及其優(yōu)先級的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • json解析時遇到英文雙引號報錯的解決方法

    json解析時遇到英文雙引號報錯的解決方法

    下面小編就為大家分享一篇json解析時遇到英文雙引號報錯的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02

最新評論

阳东县| 北川| 乐都县| 武定县| 利辛县| 德化县| 永靖县| 湘潭县| 东莞市| 南靖县| 乡宁县| 马山县| 麟游县| 遵化市| 南阳市| 桂平市| 佛坪县| 伊宁市| 东城区| 天镇县| 垦利县| 开封市| 始兴县| 廉江市| 扎兰屯市| 普安县| 弥渡县| 瑞金市| 秭归县| 济源市| 婺源县| 南郑县| 利辛县| 个旧市| 盐亭县| 平远县| 靖安县| 绥芬河市| 呼和浩特市| 乌拉特前旗| 连山|