zoukankan      html  css  js  c++  java
  • spi~动态监控目录的jar实现热加载

    对于我们自己封装的spi来说,我们可能希望他实现类似于插件的功能,例如你有一个汽车工厂,你目前有提供小汽车,如果你希望他动态支持卡车,公交车,那么spi可以帮你实现这个功能,对于我实现这个SPI功能主要由以下几个步骤组成。

    1. 对文件夹目录的监控
    2. 对文件夹里jar也的装载,动态类加载器机制实现
    3. 通过类型名称,返回实现类的列表

    具体实现

    目录监控

    /**
         * 目录监控.
         *
         * @param path
         */
        public static void watchDir(String path) {
            initClassLoader(path);
            try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
                //给path路径加上文件观察服务
                Paths.get(path).register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
                        StandardWatchEventKinds.ENTRY_MODIFY,
                        StandardWatchEventKinds.ENTRY_DELETE);
                while (true) {
                    final WatchKey key = watchService.take();
                    for (WatchEvent<?> watchEvent : key.pollEvents()) {
                        final WatchEvent.Kind<?> kind = watchEvent.kind();
                        if (kind == StandardWatchEventKinds.OVERFLOW) {
                            continue;
                        }
                        final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
                        final Path filename = watchEventPath.context();
                        System.out.println(kind + " -> " + filename);
                        initClassLoader(path);
                    }
                    boolean valid = key.reset();
                    if (!valid) {
                        break;
                    }
                }
    
            } catch (IOException | InterruptedException ex) {
                System.err.println(ex);
            }
        }
    

    目录下动态类加载器添加到当前系统加载器里

    static void initClassLoader(String path) {
            for (File file : FileUtil.loopFiles(path)) {
                System.out.println("load jar:" + file.getName());
                URL url = file.toURI().toURL();
                DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(new URL[]{url}, ClassLoader.getSystemClassLoader());
                dynamicClassLoaders.add(dynamicClassLoader);
            }
        }
    

    通过类型返回类型的实现

    /**
         * 返回所有具体的providerFactory工厂,使用dynamicClassLoaders加载器
         *
         * @param clazz
         * @param <U>
         * @return
         */
        public static <U extends ProviderFactory> List<U> getProviderFactory(Class<U> clazz) {
            List<U> list = new ArrayList<>();
            for (ClassLoader classLoader : dynamicClassLoaders) {
                ServiceLoader<U> load = ServiceLoader.load(clazz, classLoader);
                List<String> idList = list.stream().map(o -> o.getId()).collect(Collectors.toList());
                for (U providerFactory : load) {
                    if (!idList.contains(providerFactory.getId())) {
                        list.add(providerFactory);
                    }
                }
            }
            return list;
        }
    

    程序调用

    1

        @SneakyThrows
        @GetMapping("hello")
        public ResponseEntity hello() {
    
            List<String> result = new ArrayList<>();
            for (ProviderFactory u : SpiFactory.getProviderFactory(ProviderFactory.class)) {
                result.add(u.create().login());
            }
            return ResponseEntity.ok(result);
        }
    

    结果
    2

  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/lori/p/14410788.html
Copyright © 2011-2022 走看看