對於咱們本身封裝的spi來講,咱們可能但願他實現相似於插件的功能,例如你有一個汽車工廠,你目前有提供小汽車,若是你但願他動態支持卡車,公交車,那麼spi能夠幫你實現這個功能,對於我實現這個SPI功能主要由如下幾個步驟組成。app
/** * 目錄監控. * * @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; }
@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); }
結果
ide