public void loadJavaPlugins(List<MultipartFile> files, boolean save) {
        if (!allowSaveJavaPlugins && save) {
            throw new FeatureDisabledException(
                    "Cannot save Java plugins since it has been disabled");
        }
        for (MultipartFile file : files) {
            String fileName = file.name();
            ZipFile zipFile;
            File jarFile;
            if (save) {
                fileName = file.basename()
                        + ".jar";
                Path target = pluginDir.resolve(EXTERNAL_PLUGIN_ARCHIVE_NAME_PREFIX + fileName);
                if (Files.exists(target)) {
                    throw new IllegalArgumentException(
                            "The plugin jar file ("
                                    + fileName
                                    + ") already exists");
                }
                // Ensure the plugin directory exists every time
                // because it may be removed by users unexpectedly
                try {
                    Files.createDirectories(pluginDir);
                } catch (IOException e) {
                    throw new InputOutputException(
                            "Failed to create the plugin directory: "
                                    + pluginDir,
                            e);
                }
                Path source = file.file()
                        .toPath();
                try {
                    Files.move(source, target);
                } catch (IOException e) {
                    throw new InputOutputException(
                            "Failed to move the plugin JAR file from ("
                                    + source
                                    + ") to ("
                                    + target
                                    + ")",
                            e);
                }
                jarFile = target.toFile();
            } else {
                jarFile = file.file();
                jarFile.deleteOnExit();
                // We need to retain the JAR file because there may some
                // classes or resources in the JAR file haven't been loaded
                file.retain();
            }
            try {
                zipFile = new ZipFile(jarFile);
            } catch (IOException e) {
                throw new MalformedPluginArchiveException(
                        "Failed to load the jar file: "
                                + fileName,
                        e);
            }
            try {
                JavaPluginDescriptor descriptor = JavaPluginDescriptorFactory.load(zipFile);
                if (descriptor == null) {
                    throw new MalformedPluginArchiveException(
                            "Could not load a Java plugin from the file ("
                                    + fileName
                                    + ") because it is not a Java plugin JAR file");
                }
                Plugin plugin = JavaPluginFactory
                        .create(descriptor, zipFile, duplicateClassLoadStrategy, nodeType, context);
                initAndRegisterPlugin(plugin);
            } catch (Exception e) {
                try {
                    zipFile.close();
                } catch (IOException closeException) {
                    e.addSuppressed(
                            new RuntimeException("Caught an error while closing the zip file", e));
                }
                throw e;
            }
        }
    }
@implNote Start plugins after all beans are ready so that plugins can get any bean when
          starting.
turms-server-common/src/main/java/im/turms/server/common/infra/plugin/PluginManager.java