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

PowerJob的OhMyClassLoader工作流程源碼解讀

 更新時(shí)間:2024年01月18日 10:30:58   作者:codecraft  
這篇文章主要介紹了PowerJob的OhMyClassLoader工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下PowerJob的OhMyClassLoader

OhMyClassLoader

tech/powerjob/worker/container/OhMyClassLoader.java

@Slf4j
public class OhMyClassLoader extends URLClassLoader {

    public OhMyClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    /**
     * 主動(dòng)加載類,否則類加載器內(nèi)空空如也,Spring IOC容器初始化不到任何東西
     * @param packageName 包路徑,主動(dòng)加載用戶寫的類
     * @throws Exception 加載異常
     */
    public void load(String packageName) throws Exception {
        URL[] urLs = getURLs();
        for (URL jarURL : urLs) {
            JarFile jarFile = new JarFile(new File(jarURL.toURI()));
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = entries.nextElement();
                if (jarEntry.isDirectory()) {
                    continue;
                }
                String name = jarEntry.getName();
                if (!name.endsWith(".class")) {
                    continue;
                }

                // 轉(zhuǎn)換 org/spring/AAA.class -> org.spring.AAA
                String tmp = name.substring(0, name.length() - 6);
                String res = StringUtils.replace(tmp, "/", ".");

                if (res.startsWith(packageName)) {
                    loadClass(res);
                    log.info("[OhMyClassLoader] load class({}) successfully.", res);
                }
            }
        }
    }
}
OhMyClassLoader繼承了URLClassLoader,它定義了load方法,遍歷urls,挨個(gè)根據(jù)url創(chuàng)建JarFile,然后遍歷jarFile.entries(),找到.class結(jié)尾的entry,判斷是否是packageName開頭的,是則執(zhí)行父類的loadClass方法

OmsJarContainer

tech/powerjob/worker/container/OmsJarContainer.java

@Slf4j
public class OmsJarContainer implements OmsContainer {

    private final Long containerId;
    private final String name;
    private final String version;
    private final File localJarFile;
    private final Long deployedTime;

    // 引用計(jì)數(shù)器
    private final AtomicInteger referenceCount = new AtomicInteger(0);

    private OhMyClassLoader containerClassLoader;
    private ClassPathXmlApplicationContext container;

    private final Map<String, BasicProcessor> processorCache = Maps.newConcurrentMap();

    public OmsJarContainer(Long containerId, String name, String version, File localJarFile) {
        this.containerId = containerId;
        this.name = name;
        this.version = version;
        this.localJarFile = localJarFile;
        this.deployedTime = System.currentTimeMillis();
    }

    @Override
    public void init() throws Exception {

        log.info("[OmsJarContainer-{}] start to init container(name={},jarPath={})", containerId, name, localJarFile.getPath());

        URL jarURL = localJarFile.toURI().toURL();

        // 創(chuàng)建類加載器(父類加載為 Worker 的類加載)
        this.containerClassLoader = new OhMyClassLoader(new URL[]{jarURL}, this.getClass().getClassLoader());

        // 解析 Properties
        Properties properties = new Properties();
        try (InputStream propertiesURLStream = containerClassLoader.getResourceAsStream(ContainerConstant.CONTAINER_PROPERTIES_FILE_NAME)) {

            if (propertiesURLStream == null) {
                log.error("[OmsJarContainer-{}] can't find {} in jar {}.", containerId, ContainerConstant.CONTAINER_PROPERTIES_FILE_NAME, localJarFile.getPath());
                throw new PowerJobException("invalid jar file because of no " + ContainerConstant.CONTAINER_PROPERTIES_FILE_NAME);
            }

            properties.load(propertiesURLStream);
            log.info("[OmsJarContainer-{}] load container properties successfully: {}", containerId, properties);
        }
        String packageName = properties.getProperty(ContainerConstant.CONTAINER_PACKAGE_NAME_KEY);
        if (StringUtils.isEmpty(packageName)) {
            log.error("[OmsJarContainer-{}] get package name failed, developer should't modify the properties file!", containerId);
            throw new PowerJobException("invalid jar file");
        }

        // 加載用戶類
        containerClassLoader.load(packageName);

        // 創(chuàng)建 Spring IOC 容器(Spring配置文件需要填相對(duì)路徑)
        // 需要切換線程上下文類加載器以加載 JDBC 類驅(qū)動(dòng)(SPI)
        ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(containerClassLoader);
        try {
            this.container = new ClassPathXmlApplicationContext(new String[]{ContainerConstant.SPRING_CONTEXT_FILE_NAME}, false);
            this.container.setClassLoader(containerClassLoader);
            this.container.refresh();
        }finally {
            Thread.currentThread().setContextClassLoader(oldCL);
        }

        log.info("[OmsJarContainer-{}] init container(name={},jarPath={}) successfully", containerId, name, localJarFile.getPath());
    }

    //......
}
OmsJarContainer的init方法會(huì)使用構(gòu)造器傳入的localJarFile作為url創(chuàng)建OhMyClassLoader,然后讀取oms-worker-container.properties,以其中的PACKAGE_NAME屬性作為packageName,然后使用containerClassLoader.load進(jìn)行加載

deployContainer

tech/powerjob/worker/container/OmsContainerFactory.java

public static synchronized void deployContainer(ServerDeployContainerRequest request) {

        Long containerId = request.getContainerId();
        String containerName = request.getContainerName();
        String version = request.getVersion();

        log.info("[OmsContainer-{}] start to deploy container(name={},version={},downloadUrl={})", containerId, containerName, version, request.getDownloadURL());

        OmsContainer oldContainer = CARGO.get(containerId);
        if (oldContainer != null && version.equals(oldContainer.getVersion())) {
            log.info("[OmsContainer-{}] version={} already deployed, so skip this deploy task.", containerId, version);
            return;
        }

        String filePath = CONTAINER_DIR + containerId + "/" + version + ".jar";
        // 下載Container到本地
        File jarFile = new File(filePath);

        try {
            if (!jarFile.exists()) {
                FileUtils.forceMkdirParent(jarFile);
                FileUtils.copyURLToFile(new URL(request.getDownloadURL()), jarFile, 5000, 300000);
                log.info("[OmsContainer-{}] download jar successfully, path={}", containerId, jarFile.getPath());
            }

            // 創(chuàng)建新容器
            OmsContainer newContainer = new OmsJarContainer(containerId, containerName, version, jarFile);
            newContainer.init();

            // 替換容器
            CARGO.put(containerId, newContainer);
            log.info("[OmsContainer-{}] deployed new version:{} successfully!", containerId, version);

            if (oldContainer != null) {
                // 銷毀舊容器
                oldContainer.destroy();
            }

        } catch (Exception e) {
            log.error("[OmsContainer-{}] deployContainer(name={},version={}) failed.", containerId, containerName, version, e);
            // 如果部署失敗,則刪除該 jar(本次失敗可能是下載jar出錯(cuò)導(dǎo)致,不刪除會(huì)導(dǎo)致這個(gè)版本永久無法重新部署)
            CommonUtils.executeIgnoreException(() -> FileUtils.forceDelete(jarFile));
        }
    }
OmsContainerFactory提供了deployContainer方法,它會(huì)根據(jù)containerId以及version去下載指定的jar包,然后創(chuàng)建OmsJarContainer,執(zhí)行init方法

小結(jié)

OhMyClassLoader繼承了URLClassLoader,它定義了load方法,遍歷urls,挨個(gè)根據(jù)url創(chuàng)建JarFile,然后遍歷jarFile.entries(),找到.class結(jié)尾的entry,判斷是否是packageName開頭的,是則執(zhí)行父類的loadClass方法。不過這里貌似沒有對(duì)JarFile進(jìn)行關(guān)閉,可能會(huì)導(dǎo)致資源泄露。

以上就是PowerJob的OhMyClassLoader工作流程源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于PowerJob OhMyClassLoader的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java?Optional用法面試題精講

    Java?Optional用法面試題精講

    這篇文章主要為大家介紹了Java?Optional用法面試題精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • rocketmq的AclClientRPCHook權(quán)限控制使用技巧示例詳解

    rocketmq的AclClientRPCHook權(quán)限控制使用技巧示例詳解

    這篇文章主要為大家介紹了rocketmq的AclClientRPCHook使用技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Spring從@Aspect到Advisor使用演示實(shí)例

    Spring從@Aspect到Advisor使用演示實(shí)例

    這篇文章主要介紹了Spring從@Aspect到Advisor使用演示實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Swagger的使用教程詳解

    Swagger的使用教程詳解

    Swagger是一個(gè)強(qiáng)大的API文檔工具,它能夠簡(jiǎn)化API文檔的編寫和維護(hù)工作,提供了一種方便的方式來描述、展示和測(cè)試RESTful風(fēng)格的Web服務(wù)接口,本文介紹了Swagger的安裝配置和使用方法,并提供了示例代碼,感興趣的朋友一起學(xué)習(xí)吧
    2023-06-06
  • 使用Java對(duì)數(shù)據(jù)庫(kù)進(jìn)行基本的查詢和更新操作

    使用Java對(duì)數(shù)據(jù)庫(kù)進(jìn)行基本的查詢和更新操作

    這篇文章主要介紹了使用Java對(duì)數(shù)據(jù)庫(kù)進(jìn)行基本的查詢和更新操作,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10
  • SpringBoot集成SpringMVC的方法示例

    SpringBoot集成SpringMVC的方法示例

    這篇文章主要介紹了SpringBoot集成SpringMVC的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java中的原生post請(qǐng)求方式

    Java中的原生post請(qǐng)求方式

    這篇文章主要介紹了Java中的原生post請(qǐng)求方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Java8的Lambda和排序

    Java8的Lambda和排序

    這篇文章主要介紹了Java8的Lambda和排序,對(duì)數(shù)組和集合進(jìn)行排序是Java 8 lambda令人驚奇的一個(gè)應(yīng)用,我們可以實(shí)現(xiàn)一個(gè)Comparators來實(shí)現(xiàn)各種排序,下面文章將有案例詳細(xì)說明,想要了解得小伙伴可以參考一下
    2021-11-11
  • Java項(xiàng)目--家庭收支記錄程序

    Java項(xiàng)目--家庭收支記錄程序

    本文主要介紹Java基礎(chǔ)階段的一個(gè)小項(xiàng)目——家庭收支記錄程序(附完整源代碼),本項(xiàng)目所用到的主要知識(shí)點(diǎn):基本語(yǔ)法、數(shù)組和方法。本項(xiàng)目并不難,主要是對(duì)Java初學(xué)者的基礎(chǔ)綜合運(yùn)用的訓(xùn)練及檢驗(yàn)
    2021-07-07
  • SpringBoot中的文件下載功能實(shí)現(xiàn)教程

    SpringBoot中的文件下載功能實(shí)現(xiàn)教程

    SpringBoot文件下載分兩種方式:直接流式下載(實(shí)時(shí)生成內(nèi)容,適合小文件)與靜態(tài)資源映射(預(yù)先存儲(chǔ)文件,適合大文件),實(shí)現(xiàn)涉及控制器調(diào)用及分頁(yè)數(shù)據(jù)處理流程
    2025-09-09

最新評(píng)論

昭平县| 寿阳县| 金塔县| 合山市| 尼木县| 万全县| 加查县| 溧阳市| 抚宁县| 丰镇市| 司法| 钟祥市| 镇坪县| 凉城县| 莒南县| 清远市| 铁力市| 抚宁县| 三亚市| 连城县| 石林| 隆安县| 苍南县| 黄龙县| 赤城县| 阿尔山市| 舟山市| 仲巴县| 江永县| 盐边县| 通榆县| 永川市| 寻甸| 武隆县| 台安县| 耿马| 双辽市| 陆丰市| 昭平县| 临泉县| 栾城县|