久久久精品一区ed2k-女人被男人叉到高潮的视频-中文字幕乱码一区久久麻豆樱花-俄罗斯熟妇真实视频

Java類加載器(死磕9)

【正文】Java類加載器(? CLassLoader ) 死磕9:?

10余年的瀘州網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整瀘州建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“瀘州網(wǎng)站設(shè)計”,“瀘州網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實(shí)執(zhí)行。

上下文加載器原理和案例

本小節(jié)目錄

9.1. 父加載器不能訪問子加載器的類
9.2. 一個寵物工廠接口
9.3. 一個寵物工廠管理類
9.4 APPClassLoader不能訪問子加載器中的類
9.5. 線程上下文類加載器


類加載器的代理模式并不能解決 Java 應(yīng)用開發(fā)中會遇到的類加載器的全部問題。Java 提供了很多服務(wù)提供者接口(Service Provider Interface,SPI),允許第三方為這些接口提供實(shí)現(xiàn)。常見的 SPI 有 JDBC、JCE、JNDI、JAXP 和 JBI 等。這些 SPI 的接口由 Java 核心庫來提供,如 JAXP 的 SPI 接口定義包含在 javax.xml.parsers包中。這些 SPI 的實(shí)現(xiàn)代碼很可能是作為 Java 應(yīng)用所依賴的 jar 包被包含進(jìn)來,可以通過類路徑(CLASSPATH)來找到,如實(shí)現(xiàn)了 JAXP SPI 的 Apache Xerces所包含的 jar 包。SPI 接口中的代碼經(jīng)常需要加載具體的實(shí)現(xiàn)類。如 JAXP 中的 javax.xml.parsers.DocumentBuilderFactory類中的 newInstance()方法用來生成一個新的 DocumentBuilderFactory的實(shí)例。這里的實(shí)例的真正的類是繼承自 javax.xml.parsers.DocumentBuilderFactory,由 SPI 的實(shí)現(xiàn)所提供的。如在 Apache Xerces 中,實(shí)現(xiàn)的類是 org.apache.xerces.jaxp.DocumentBuilderFactoryImpl。而問題在于,SPI 的接口是 Java 核心庫的一部分,是由引導(dǎo)類加載器來加載的;SPI 實(shí)現(xiàn)的 Java 類一般是由系統(tǒng)類加載器來加載的。引導(dǎo)類加載器是無法找到 SPI 的實(shí)現(xiàn)類的,因為它只加載 Java 的核心庫。它也不能代理給系統(tǒng)類加載器,因為它是系統(tǒng)類加載器的祖先類加載器。也就是說,類加載器的代理模式無法解決這個問題。

線程上下文類加載器(context class loader)是從 JDK 1.2 開始引入的。

在類java.lang.Thread中的方法 getContextClassLoader()和 setContextClassLoader(ClassLoader cl)用來獲取和設(shè)置線程的上下文類加載器。

如果沒有通過 setContextClassLoader(ClassLoader cl)方法進(jìn)行設(shè)置的話,線程將繼承其父線程的上下文類加載器。Java 應(yīng)用運(yùn)行的初始線程的上下文類加載器是AppClassLoader類加載器。

線程上下文類加載器正好解決了這個問題。如果不做任何的設(shè)置,Java 應(yīng)用的線程的上下文類加載器默認(rèn)就是系統(tǒng)上下文類加載器。在 SPI 接口的代碼中使用線程上下文類加載器,就可以成功的加載到 SPI 實(shí)現(xiàn)的類。線程上下文類加載器在很多 SPI 的實(shí)現(xiàn)中都會用到。

1.1.1. 父加載器不能訪問子加載器的類

關(guān)于父加載器,不能訪問子加載器加載的類,是一個比較大的問題,舉個栗子。

1.1.2. 一個寵物工廠接口

這里有一個寵物工廠接口:

face IPetFactory {

    /**

     * 根據(jù)類型,構(gòu)造一個對象

     * @param type 類型,如 Type.CAT

     * @return

     */

    IPet buildePet(IPet.Type type);

}

1.1.3. 一個寵物工廠管理類

還有一個寵物工廠管理類,根據(jù)類名,加載工廠實(shí)現(xiàn)類。

public class FactoryManager

{

    /**

     * 單例的Pet實(shí)例工廠

     */

    private static IPetFactory petFactory;

    /**

     * 已經(jīng)類名,取得工廠實(shí)例

     *

     * @param factoryClassName

     * @return

     */

    public static IPetFactory getInstance(String factoryClassName)

    {

        if (null != petFactory)

        {

            return petFactory;

        }

        if (null == factoryClassName)

        {

            //默認(rèn)的實(shí)現(xiàn)

            factoryClassName = "com.crazymakercircle.petStore.pet.factory.PetFactoryImpl";

        }

        /**

         * 獲得線程上下文加載器

         */

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        try

        {

//            Class<?> factoryClass = loader.loadClass(factoryClassName);

            Class<?>   factoryClass=Class.forName(factoryClassName);

            petFactory = (IPetFactory) factoryClass.newInstance();

        } catch (Exception e)

        {

            e.printStackTrace();

        }

        return petFactory;

    }

}

1.1.4. APPClassLoader不能訪問子加載器中的類

先上代碼:

public class FailCase

{

   private static IPetFactory petFactory=null;

    public static void testLoader()

    {

        try

        {

            String baseDir = SystemConfig.PET_LIB_PATH;

            FileClassLoader classLoader = new FileClassLoader(baseDir);

            String className = SystemConfig.PET_FACTORY_CLASS;

            Class petFactoryClass = classLoader.loadClass(className);

            Logger.info("顯示petFactoryClass 的ClassLoader tree:");

            ClassLoaderUtil.showLoader4Class(petFactoryClass);

            petFactory = FactoryManager.getInstance(className);

        } catch (ClassNotFoundException e)

        {

            e.printStackTrace();

        }

    }

    public static void showPet()

    {

        IPet dog=petFactory.buildePet(IPet.Type.DOG);

        dog.sayHello();

    }

    public static void main(String[] args)

    {

        testLoader();

        showPet();

    }

}

運(yùn)行上面的栗子,試一試。

發(fā)現(xiàn),是失敗的。

原因是,F(xiàn)actoryManager是APPClassLoader加載的,而第三方的工廠類是FileClassLoader 加載的。

FileClassLoader 是APPClassLoader的子加載器。子加載器可以訪問父加載器中的類,但是父親不能訪問子加載器中的類。

所以,F(xiàn)actoryManager沒有辦法load子加載器中的工廠實(shí)現(xiàn)類。

1.1.5. 線程上下文類加載器

使用線程上下文類加載器,可以在執(zhí)行線程中拋棄雙親委派加載鏈模式,使用線程上下文里的類加載器加載類。

public class CorrectCase

{

   private static IPetFactory petFactory=null;

    public static void testLoader()

    {

        try

        {

            String baseDir = SystemConfig.PET_LIB_PATH;

            FileClassLoader classLoader = new FileClassLoader(baseDir);

            Thread.currentThread().setContextClassLoader(classLoader);

            String className = SystemConfig.PET_FACTORY_CLASS;

            petFactory = FactoryManager.getInstance(className);

            Class petFactoryClass = classLoader.loadClass(className);

            Logger.info("顯示petFactoryClass 的ClassLoader tree:");

            ClassLoaderUtil.showLoader4Class(petFactoryClass);

        } catch (ClassNotFoundException e)

        {

            e.printStackTrace();

        }

    }

    public static void showPet()

    {

        IPet dog=petFactory.buildePet(IPet.Type.DOG);

        dog.sayHello();

    }

    public static void main(String[] args)

    {

        testLoader();

        showPet();

    }

}

將FileClassLoader設(shè)置成為線程上下文加載器,然后,在工廠管理器中,使用線程上限加載器加載:

public class FactoryManager

{

    /**

     * 單例的Pet實(shí)例工廠

     */

    private static IPetFactory petFactory;

    /**

     * 已經(jīng)類名,取得工廠實(shí)例

     *

     * @param factoryClassName

     * @return

     */

    public static IPetFactory getInstance(String factoryClassName)

    {

        if (null != petFactory)
        {
            return petFactory;
        }

        if (null == factoryClassName)
        {
            //默認(rèn)的實(shí)現(xiàn)
           factoryClassName ="com.crazymakercircle.petStore.pet.factory.PetFactoryImpl";

        }

        /**

         * 獲得線程上下文加載器

         */

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        try

        {
            Class<?> factoryClass = loader.loadClass(factoryClassName);
            petFactory = (IPetFactory) factoryClass.newInstance();

        } catch (Exception e)

        {

            e.printStackTrace();

        }

        return petFactory;

    }

}


源碼:

代碼工程:? classLoaderDemo.zip

下載地址:在瘋狂創(chuàng)客圈QQ群文件共享。


瘋狂創(chuàng)客圈:如果說Java是一個武林,這里的聚集一群武癡, 交流編程體驗心得
QQ群鏈接:
瘋狂創(chuàng)客圈QQ群

無編程不創(chuàng)客,無案例不學(xué)習(xí)。 一定記得去跑一跑案例哦

類加載器系列全目錄

1.導(dǎo)入

2. JAVA類加載器分類

3. 揭秘ClassLoader抽象基類

4. 神秘的雙親委托機(jī)制

5. 入門案例:自定義一個文件系統(tǒng)的自定義classLoader

6. 基礎(chǔ)案例:自定義一個網(wǎng)絡(luò)類加載器

7. 中級案例:設(shè)計一個加密的自定義網(wǎng)絡(luò)加載器

8. 高級案例1:使用ASM技術(shù),結(jié)合類加載器,解密AOP原理

9. 高級案例2:上下文加載器原理和案例

當(dāng)前名稱:Java類加載器(死磕9)
標(biāo)題網(wǎng)址:http://sd-ha.com/article28/ghdejp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、網(wǎng)站維護(hù)、網(wǎng)站營銷、軟件開發(fā)、搜索引擎優(yōu)化、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)