深圳手机网站门户媒体有哪些
- 作者: 五速梦信息网
- 时间: 2026年04月20日 09:19
当前位置: 首页 > news >正文
深圳手机网站,门户媒体有哪些,wordpress+资源站模板,设备报价单模板文章目录 Pre工程结构概述1. 插件接口与实现分析2. 插件工厂初始化分析3. 插件项包装类解析4. 插件工厂方法解析5. 插件加载与资源释放机制6. 实现类小结附PluginFactory Pre 插件 - 通过SPI方式实现插件管理 插件 - 一份配置#xff0c;离插件机制只有一步之遥 插件 - 插件… 文章目录 Pre工程结构概述1. 插件接口与实现分析2. 插件工厂初始化分析3. 插件项包装类解析4. 插件工厂方法解析5. 插件加载与资源释放机制6. 实现类小结附PluginFactory Pre 插件 - 通过SPI方式实现插件管理 插件 - 一份配置离插件机制只有一步之遥 插件 - 插件机制触手可及 Plugin - 插件开发01_SPI的基本使用 Plugin - 插件开发02_使用反射机制和自定义配置实现插件化开发 Plugin - 插件开发03_Spring Boot动态插件化与热加载 Plugin - 插件开发04_Spring Boot中的SPI机制与Spring Factories实现 Plugin - 插件开发05_Solon中的插件实现机制 工程结构 概述 接下来我们主要对IPlugin接口及其实现以及插件的加载和管理机制进行分析分为如下几个点 插件接口与实现分析插件工厂初始化分析插件项包装类解析插件工厂方法解析插件加载与资源释放机制 1. 插件接口与实现分析 插件机制的核心接口是IPlugin IPlugin继承了AutoCloseable接口确保插件可以被正确关闭。 此外还有一个IDefaultPlugin接口继承了IPlugin用于定义默认插件。 接口的主要代码如下 import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ClassUtil; import com.alibaba.fastjson.JSONObject;import java.util.HashMap; import java.util.Map;/*** 插件模块接口** author bwcx_jzy* since 2021/12/22/ public interface IPlugin extends AutoCloseable {/** 执行插件方法** param main 拦截到到对象* param parameter 执行方法传人的参数* return 返回值* throws Exception 异常/Object execute(Object main, MapString, Object parameter) throws Exception;/** 执行插件方法** param main 主参数* param parameters 其他参数* return 结果* throws Exception 异常/default Object execute(Object main, Object… parameters) throws Exception {// 处理参数int length parameters.length;MapString, Object map new HashMap(length / 2);for (int i 0; i length; i 2) {map.put(parameters[i].toString(), parameters[i 1]);}return this.execute(main, map);}/** 执行插件方法** param main 拦截到到对象* param parameters 其他参数* param T 泛型* param cls 返回值类型* return 返回值* throws Exception 异常/default T T execute(Object main, ClassT cls, Object… parameters) throws Exception {Object execute this.execute(main, parameters);return this.convertResult(execute, cls);}/** 执行插件方法** param main 拦截到到对象* param parameter 执行方法传人的参数* param T 泛型* param cls 返回值类型* return 返回值* throws Exception 异常/default T T execute(Object main, MapString, Object parameter, ClassT cls) throws Exception {Object execute this.execute(main, parameter);return this.convertResult(execute, cls);}/** 转换结果** param execute 结果* param cls 返回值类型* param T 泛型* return 返回值类型/SuppressWarnings(unchecked)default T T convertResult(Object execute, ClassT cls) {if (execute null) {return null;}Class? aClass execute.getClass();if (ClassUtil.isSimpleValueType(aClass)) {return (T) Convert.convert(aClass, execute);}// json 数据Object o JSONObject.toJSON(execute);if (o instanceof JSONObject) {JSONObject jsonObject (JSONObject) o;return jsonObject.toJavaObject(cls);}return (T) execute;}/** 系统关闭插件资源释放** throws Exception 异常/Overridedefault void close() throws Exception {} } 主要方法解析 execute 方法 execute(Object main, ClassT cls, Object… parameters)此方法接收一个对象、一个返回值类型和一组参数执行插件方法后返回指定类型的结果。execute(Object main, MapString, Object parameter, ClassT cls)此方法接收一个对象、一个参数Map和一个返回值类型执行插件方法后返回指定类型的结果。 convertResult 方法 该方法用于将执行结果转换为指定类型。它首先判断结果是否为简单类型如果是则直接转换否则将结果转换为JSON对象再将JSON对象转换为指定类型。 close 方法 实现了AutoCloseable接口用于在系统关闭时释放插件资源。默认实现为空方法。 2. 插件工厂初始化分析 插件工厂类PluginFactory负责插件的初始化和管理 实现了ApplicationContextInitializer和ApplicationListener接口用于在Spring上下文初始化和关闭时进行插件的加载和资源释放。 初始化核心方法的主要代码如下 Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {init();// 扫描插件 实现SetClass? classes ClassUtil.scanPackage(io.jpom, IPlugin.class::isAssignableFrom);ListPluginItemWrap pluginItemWraps classes.stream().filter(aClass - ClassUtil.isNormalClass(aClass) aClass.isAnnotationPresent(PluginConfig.class)).map(aClass - new PluginItemWrap((Class? extends IPlugin) aClass)).filter(pluginItemWrap - {if (StrUtil.isEmpty(pluginItemWrap.getName())) {DefaultSystemLog.getLog().warn(plugin config name error:{}, pluginItemWrap.getClassName());return false;}return true;}).collect(Collectors.toList());//MapString, ListPluginItemWrap pluginMap CollStreamUtil.groupByKey(pluginItemWraps, PluginItemWrap::getName);pluginMap.forEach((key, value) - {// 排序value.sort((o1, o2) - Comparator.comparingInt((ToIntFunctionPluginItemWrap) value1 - {Order order value1.getClassName().getAnnotation(Order.class);if (order null) {return 0;}return order.value();}).compare(o1, o2));PLUGIN_MAP.put(key, value);});log.debug(load plugin count:{}, pluginMap.keySet().size());} 3. 插件项包装类解析 PluginItemWrap类用于封装插件的相关信息如插件配置、插件名、插件类名和插件对象实现了对插件的包装和插件实例的创建。 import cn.hutool.core.util.ReflectUtil; import cn.jiangzeyin.common.spring.SpringUtil; import lombok.Getter;/** 插件端对象** author bwcx_jzy* since 2021/12/24/ Getter public class PluginItemWrap {/** 配置相关/private final PluginConfig pluginConfig;/** 插件名/private final String name;/** 插件类名/private final Class? extends IPlugin className;/** 插件对象/private volatile IPlugin plugin;public PluginItemWrap(Class? extends IPlugin className) {this.className className;this.pluginConfig className.getAnnotation(PluginConfig.class);this.name this.pluginConfig.name();}public IPlugin getPlugin() {if (plugin null) {synchronized (className) {if (plugin null) {//boolean nativeObject this.pluginConfig.nativeObject();if (nativeObject) {plugin ReflectUtil.newInstance(className);} else {plugin SpringUtil.getBean(className);}}}}return plugin;} } 4. 插件工厂方法解析 插件工厂提供了若干静态方法供外部使用如获取插件对象、判断是否包含某个插件以及获取插件数量等。 public static IPlugin getPlugin(String name) {ListPluginItemWrap pluginItemWraps PLUGIN_MAP.get(name);PluginItemWrap first CollUtil.getFirst(pluginItemWraps);Assert.notNull(first, 对应找到对应到插件 name);return first.getPlugin(); }public static boolean contains(String name) {return PLUGIN_MAP.containsKey(name); }public static int size() {return PLUGIN_MAP.size(); }5. 插件加载与资源释放机制 在PluginFactory文件中实现了插件的加载和资源释放机制。在init方法中扫描指定包下的插件并加载。在onApplicationEvent方法中监听Spring上下文关闭事件并释放插件资源。 这两个方法的主要代码如下 private static void init() {File runPath JpomManifest.getRunPath().getParentFile();File plugin FileUtil.file(runPath, plugin);if (!plugin.exists() || plugin.isFile()) {return;}// 加载二级插件包File[] dirFiles plugin.listFiles(File::isDirectory);if (dirFiles ! null) {for (File file : dirFiles) {File lib FileUtil.file(file, lib);if (!lib.exists() || lib.isFile()) {continue;}File[] listFiles lib.listFiles((dir, name) - StrUtil.endWith(name, FileUtil.JAR_FILE_EXT, true));if (listFiles null || listFiles.length 0) {continue;}for (File listFile : listFiles) {addPlugin(file.getName(), listFile);}}}// 加载一级独立插件端包File[] files plugin.listFiles(pathname - FileUtil.isFile(pathname) FileUtil.JAR_FILE_EXT.equalsIgnoreCase(FileUtil.extName(pathname)));if (files ! null) {for (File file : files) {addPlugin(file.getName(), file);}} }Override public void onApplicationEvent(ContextClosedEvent event) {CollectionListPluginItemWrap values PLUGIN_MAP.values();for (ListPluginItemWrap value : values) {for (PluginItemWrap pluginItemWrap : value) {IPlugin plugin pluginItemWrap.getPlugin();IoUtil.close(plugin);}} }6. 实现类 我们以DefaultDbH2PluginImpl插件实现分析插件的视线 它实现了IPlugin接口中定义的方法。 PluginConfig(name db-h2) public class DefaultDbH2PluginImpl implements IDefaultPlugin {Overridepublic Object execute(Object main, MapString, Object parameter) throws Exception {String method StrUtil.toString(main);if (StrUtil.equals(backupSql, method)) {String url (String) parameter.get(url);String user (String) parameter.get(user);String password (String) parameter.get(pass);String backupSqlPath (String) parameter.get(backupSqlPath);ListString tableNameList (ListString) parameter.get(tableNameList);this.backupSql(url, user, password, backupSqlPath, tableNameList);} else if (StrUtil.equals(restoreBackupSql, method)) {String backupSqlPath (String) parameter.get(backupSqlPath);DataSource dataSource (DataSource) parameter.get(dataSource);if (dataSource null) {// 加载数据源dataSource DSFactory.get();}this.restoreBackupSql(backupSqlPath, dataSource);} else if (StrUtil.equals(recoverToSql, method)) {File dbPath (File) parameter.get(dbPath);String dbName (String) parameter.get(dbName);File recoverBackup (File) parameter.get(recoverBackup);return this.recover(dbPath, dbName, recoverBackup);} else {throw new IllegalArgumentException(不支持的类型);}return done;}/** 恢复** param dbPath 数据库路径* param dbName 数据库名* param recoverBackup 恢复到哪个路径* return 返回恢复到 sql 文件* throws SQLException sql/private File recover(File dbPath, String dbName, File recoverBackup) throws SQLException {String dbLocalPath FileUtil.getAbsolutePath(dbPath);ArrayListString list FileLister.getDatabaseFiles(dbLocalPath, dbName, true);if (CollUtil.isEmpty(list)) {return null;}FileUtil.mkdir(recoverBackup);// 备份数据for (String s : list) {FileUtil.move(FileUtil.file(s), recoverBackup, true);}String absolutePath FileUtil.getAbsolutePath(recoverBackup);Console.log(h2 db recover backup path,{}, absolutePath);// 恢复数据Recover recover new Recover();recover.runTool(-dir, absolutePath, -db, dbName);return FileUtil.file(recoverBackup, dbName .h2.sql);}/** 备份 SQL** param url jdbc url* param user user* param password password* param backupSqlPath backup SQL file path, absolute path* param tableNameList backup table name list, if need backup all table, use null*/private void backupSql(String url, String user, String password,String backupSqlPath, ListString tableNameList) throws SQLException {// 备份 SQLString sql StrUtil.format(SCRIPT DROP to {}, backupSqlPath);// 判断是否部分部分表if (!CollectionUtils.isEmpty(tableNameList)) {String tableNames StrUtil.join(StrUtil.COMMA, tableNameList.toArray());sql StrUtil.format({} TABLE {}, sql, tableNames);}DefaultSystemLog.getLog().debug(backup SQL is: {}, sql);// 执行 SQL 备份脚本Shell shell new Shell();/url 表示 h2 数据库的 jdbc url user 表示登录的用户名* password 表示登录密码* driver 是 jdbc 驱动* sql 是备份的 sql 语句* - 案例script drop to \({fileName1} table \){tableName1},\({tableName2}...* - script drop to 表示备份数据库drop 表示建表之前会先删除表* - \){fileName1} 表示备份之后的文件名* - table 表示需要备份的表名称后面跟多个表名用英文逗号分割/String[] params new String[]{-url, url,-user, user,-password, password,-driver, org.h2.Driver,-sql, sql};try (FastByteArrayOutputStream arrayOutputStream new FastByteArrayOutputStream()) {try (PrintStream printStream new PrintStream(arrayOutputStream)) {shell.setOut(printStream);shell.runTool(params);}}}/** 还原备份 SQL** param backupSqlPath backup SQL file path, absolute path* throws SQLException SQLException* throws IOException FileNotFoundException*/private void restoreBackupSql(String backupSqlPath, DataSource dataSource) throws SQLException, IOException {Assert.notNull(dataSource, Restore Backup sql error…H2 DataSource not null);try (Connection connection dataSource.getConnection()) {// 读取数据库备份文件执行还原File backupSqlFile FileUtil.file(backupSqlPath);try (FileReader fileReader new FileReader(backupSqlFile)) {RunScript.execute(connection, fileReader);}}} } 小结 在Jpom项目中IPlugin接口是插件系统的核心接口它定义了插件需要实现的基本方法。 在插件工厂类PluginFactory中通过扫描类路径加载插件并进行初始化 IPlugin接口及其实现为Jpom的插件系统提供了灵活的扩展能力。通过定义通用的执行方法和结果转换方法IPlugin接口简化了插件的开发和集成过程。而插件工厂类PluginFactory则通过扫描和加载机制实现了插件的自动发现和初始化使得插件系统具有高度的可扩展性和灵活性。 通过对插件接口IPlugin、插件工厂PluginFactory、插件项包装类PluginItemWrap以及插件的加载和资源释放机制的分析可以清晰地了解整个工程的插件机制。这为后续的插件开发和管理提供了坚实的基础。 附PluginFactory Slf4j public class PluginFactory implements ApplicationContextInitializerConfigurableApplicationContext, ApplicationListenerContextClosedEvent {// private static final ListFeatureCallback FEATURE_CALLBACKS new ArrayList();private static final MapString, ListPluginItemWrap PLUGIN_MAP new ConcurrentHashMap();// /** // * 添加回调事件 // * // * param featureCallback 回调 // / // public static void addFeatureCallback(FeatureCallback featureCallback) { // FEATURE_CALLBACKS.add(featureCallback); // } // // public static ListFeatureCallback getFeatureCallbacks() { // return FEATURE_CALLBACKS; // }/** 获取插件端** param name 插件名* return 插件对象/public static IPlugin getPlugin(String name) {ListPluginItemWrap pluginItemWraps PLUGIN_MAP.get(name);PluginItemWrap first CollUtil.getFirst(pluginItemWraps);Assert.notNull(first, 对应找到对应到插件 name);return first.getPlugin();}/** 判断是否包含某个插件** param name 插件名* return true 包含/public static boolean contains(String name) {return PLUGIN_MAP.containsKey(name);}/** 插件数量** return 当前加载的插件数量/public static int size() {return PLUGIN_MAP.size();}/** 正式环境添加依赖*/private static void init() {File runPath JpomManifest.getRunPath().getParentFile();File plugin FileUtil.file(runPath, plugin);if (!plugin.exists() || plugin.isFile()) {return;}// 加载二级插件包File[] dirFiles plugin.listFiles(File::isDirectory);if (dirFiles ! null) {for (File file : dirFiles) {File lib FileUtil.file(file, lib);if (!lib.exists() || lib.isFile()) {continue;}File[] listFiles lib.listFiles((dir, name) - StrUtil.endWith(name, FileUtil.JAR_FILE_EXT, true));if (listFiles null || listFiles.length 0) {continue;}addPlugin(file.getName(), lib);}}// 加载一级独立插件端包File[] files plugin.listFiles(pathname - FileUtil.isFile(pathname) FileUtil.JAR_FILE_EXT.equalsIgnoreCase(FileUtil.extName(pathname)));if (files ! null) {for (File file : files) {addPlugin(file.getName(), file);}}}private static void addPlugin(String pluginName, File file) {DefaultSystemLog.getLog().info(加载{} 插件, pluginName);ClassLoader contextClassLoader ClassLoaderUtil.getClassLoader();JarClassLoader.loadJar((URLClassLoader) contextClassLoader, file);}Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {init();// 扫描插件 实现SetClass? classes ClassUtil.scanPackage(io.jpom, IPlugin.class::isAssignableFrom);ListPluginItemWrap pluginItemWraps classes.stream().filter(aClass - ClassUtil.isNormalClass(aClass) aClass.isAnnotationPresent(PluginConfig.class)).map(aClass - new PluginItemWrap((Class? extends IPlugin) aClass)).filter(pluginItemWrap - {if (StrUtil.isEmpty(pluginItemWrap.getName())) {DefaultSystemLog.getLog().warn(plugin config name error:{}, pluginItemWrap.getClassName());return false;}return true;}).collect(Collectors.toList());//MapString, ListPluginItemWrap pluginMap CollStreamUtil.groupByKey(pluginItemWraps, PluginItemWrap::getName);pluginMap.forEach((key, value) - {// 排序value.sort((o1, o2) - Comparator.comparingInt((ToIntFunctionPluginItemWrap) value1 - {Order order value1.getClassName().getAnnotation(Order.class);if (order null) {return 0;}return order.value();}).compare(o1, o2));PLUGIN_MAP.put(key, value);});log.debug(load plugin count:{}, pluginMap.keySet().size());}Overridepublic void onApplicationEvent(ContextClosedEvent event) {CollectionListPluginItemWrap values PLUGIN_MAP.values();for (ListPluginItemWrap value : values) {for (PluginItemWrap pluginItemWrap : value) {IPlugin plugin pluginItemWrap.getPlugin();IoUtil.close(plugin);}}} }
- 上一篇: 深圳手机网站成全高清视频免费观看
- 下一篇: 深圳苏州企业网站建设服务网站怎么弄缩略图上传
相关文章
-
深圳手机网站成全高清视频免费观看
深圳手机网站成全高清视频免费观看
- 技术栈
- 2026年04月20日
-
深圳视频网站开发网页设计素材 旅游
深圳视频网站开发网页设计素材 旅游
- 技术栈
- 2026年04月20日
-
深圳市做物流网站dede自定义网站地图
深圳市做物流网站dede自定义网站地图
- 技术栈
- 2026年04月20日
-
深圳苏州企业网站建设服务网站怎么弄缩略图上传
深圳苏州企业网站建设服务网站怎么弄缩略图上传
- 技术栈
- 2026年04月20日
-
深圳通公司网站个人网页设计理念
深圳通公司网站个人网页设计理念
- 技术栈
- 2026年04月20日
-
深圳外贸建站模板天津建设安全协会网站
深圳外贸建站模板天津建设安全协会网站
- 技术栈
- 2026年04月20日
