From 8c620767e0140f7a8886b42ea969d50b9fc2a3b1 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Fri, 25 Oct 2019 14:48:12 +0800 Subject: [PATCH 1/9] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E6=94=B9=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E8=B7=AF=E5=BE=84=E5=AE=89=E8=A3=85=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=90=8E,=20=E5=8D=B8=E8=BD=BD=E5=90=8E=E8=AF=A5=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=90=8E,=20=E5=8E=9F=E6=8F=92=E4=BB=B6=E4=BC=9A?= =?UTF-8?q?=E5=8F=98=E6=88=900k=20=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82=202?= =?UTF-8?q?=E3=80=81=E4=BC=98=E5=8C=96=E5=A4=87=E4=BB=BD=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/basic/example/main/plugin/Hello.java | 16 +++++ .../example/main/rest/HelloResource.java | 23 ++++++++ .../example/plugin1/service/HelloImp1.java | 16 +++++ .../operator/DefaultPluginOperator.java | 58 ++++++++++++++----- .../integration/operator/PluginOperator.java | 16 +++-- .../integration/user/PluginUser.java | 27 ++++++++- 6 files changed, 132 insertions(+), 24 deletions(-) create mode 100644 example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/Hello.java create mode 100644 example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/service/HelloImp1.java diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/Hello.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/Hello.java new file mode 100644 index 0000000..197595b --- /dev/null +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/Hello.java @@ -0,0 +1,16 @@ +package com.basic.example.main.plugin; + +import org.pf4j.ExtensionPoint; + +/** + * 测试非Spring管理的bean接口 + * 实现类需要使用 @Extension 注解 + * + * @author zhangzhuo + * @version 1.0 + */ +public interface Hello extends ExtensionPoint { + + String getName(); + +} diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java index 2e28b81..8d35858 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java @@ -1,5 +1,6 @@ package com.basic.example.main.rest; +import com.basic.example.main.plugin.Hello; import com.gitee.starblues.integration.PluginApplication; import com.gitee.starblues.integration.user.PluginUser; import com.basic.example.main.plugin.ConsoleName; @@ -101,6 +102,28 @@ public class HelloResource { return getConsoleNames(stringBuffer, consoleNames); } + + /** + * 通过 插件id 获取指定的插件中的实现类 + * 打印实现接口 com.basic.demo.main.main.plugin.ConsoleName 的实现类 + * @return 返回所有实现 com.basic.demo.main.main.plugin.ConsoleName 接口的实现类的 name() 方法的输出 + */ + @GetMapping("/extensions") + public String hello(){ + + List hellos = pluginUser.getPluginExtensions(Hello.class); + if(hellos == null){ + return "Not impl Hello"; + } else { + StringBuffer stringBuffer = new StringBuffer("extensions impl :
"); + for (Hello hello : hellos) { + stringBuffer.append(hello.getName()) + .append("
"); + } + return stringBuffer.toString(); + } + } + /** * 调用接口 name() 方法,并拼接输出 * @param stringBuffer stringBuffer diff --git a/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/service/HelloImp1.java b/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/service/HelloImp1.java new file mode 100644 index 0000000..ee3213b --- /dev/null +++ b/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/service/HelloImp1.java @@ -0,0 +1,16 @@ +package com.basic.example.plugin1.service; + +import com.basic.example.main.plugin.Hello; + +/** + * description + * + * @author zhangzhuo + * @version 1.0 + */ +public class HelloImp1 implements Hello { + @Override + public String getName() { + return "my name is hello imp1 of plugin1"; + } +} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index 872c1c4..8a0d102 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -111,14 +111,32 @@ public class DefaultPluginOperator implements PluginOperator { } String pluginId = null; try { - pluginId = pluginManager.loadPlugin(path); + if(!Files.exists(path)){ + throw new FileNotFoundException("Not found this path " + path); + } + Path pluginsRoot = pluginManager.getPluginsRoot(); + if(path.getParent().compareTo(pluginsRoot) == 0){ + // 说明该插件文件存在于插件root目录下。 + pluginId = pluginManager.loadPlugin(path); + } else { + File sourceFile = path.toFile(); + String targetPathString = pluginsRoot.toString() + File.separator + + sourceFile.getName(); + Path targetPath = PluginFileUtils.getExistPath(Paths.get(targetPathString)); + if(Files.exists(targetPath)){ + // 如果存在该文件, 则备份 + backup(targetPath, "install-backup", 2); + } + FileUtils.copyFile(sourceFile, targetPath.toFile()); + pluginId = pluginManager.loadPlugin(targetPath); + } if(StringUtils.isEmpty(pluginId)){ log.error("Install plugin '{}' failure, this plugin id is empty.", pluginId); return false; } GlobalRegistryInfo.addOperatorPluginInfo(pluginId, PluginOperatorInfo.OperatorType.INSTALL, true); if(start(pluginId)){ - log.info("Install plugin '{}' success. {}", pluginId); + log.info("Install plugin '{}' success", pluginId); return true; } else { log.error("Install plugin '{}' failure", pluginId); @@ -159,7 +177,7 @@ public class DefaultPluginOperator implements PluginOperator { try { if (pluginManager.unloadPlugin(pluginId)) { // 卸载完后,将插件文件移到备份文件中 - backup(pluginWrapper.getPluginPath(), "uninstallPlugin", 1); + backup(pluginWrapper.getPluginPath(), "uninstall", 1); log.info("Uninstall plugin '{}' success", pluginId); return true; } else { @@ -262,6 +280,9 @@ public class DefaultPluginOperator implements PluginOperator { String configPath = integrationConfiguration.pluginConfigFilePath() + File.separator + sourceFile.getName(); Path targetPath = PluginFileUtils.getExistPath(Paths.get(configPath)); + if(Files.exists(targetPath)){ + backup(targetPath, "install-config-backup",2); + } FileUtils.copyFile(sourceFile, targetPath.toFile()); return true; } @@ -274,22 +295,25 @@ public class DefaultPluginOperator implements PluginOperator { String fileName = configFile.getOriginalFilename(); String configPath = integrationConfiguration.pluginConfigFilePath() + File.separator + fileName; - Path srcPath = PluginFileUtils.getExistPath(Paths.get(configPath)); - Files.write(srcPath, configFile.getBytes()); + Path targetPath = PluginFileUtils.getExistPath(Paths.get(configPath)); + if(Files.exists(targetPath)){ + backup(targetPath, "upload-config-backup",2); + } + Files.write(targetPath, configFile.getBytes()); return true; } @Override - public boolean backupPlugin(Path path, String appendName) throws Exception { + public boolean backupPlugin(Path path, String sign) throws Exception { Objects.requireNonNull(path); - return backup(path, appendName, 2); + return backup(path, sign, 2); } @Override - public boolean backupPlugin(String pluginId, String appendName) throws Exception { + public boolean backupPlugin(String pluginId, String sign) throws Exception { PluginWrapper pluginManager = getPluginWrapper(pluginId, "BackupPlugin by pluginId"); - return backupPlugin(pluginManager.getPluginPath(), appendName); + return backupPlugin(pluginManager.getPluginPath(), sign); } @Override @@ -362,7 +386,7 @@ public class DefaultPluginOperator implements PluginOperator { File target = pluginFilePath.toFile(); if(target.exists()){ // 存在则拷贝一份 - backup(pluginFilePath, "uploadPlugin", 2); + backup(pluginFilePath, "upload", 2); } FileUtils.copyFile(verifyPath.toFile(), target); // 删除临时文件 @@ -415,12 +439,12 @@ public class DefaultPluginOperator implements PluginOperator { /** * 备份 * @param sourcePath 源文件的路径 - * @param appendName 追加的字符串 + * @param sign 文件标志 * @param type 类型 1移动 2拷贝 * @return 结果 * @throws Exception Exception */ - private boolean backup(Path sourcePath, String appendName, int type) throws Exception { + private boolean backup(Path sourcePath, String sign, int type) throws Exception { if(isDev()){ // 如果是开发环境, 则不进行备份 return true; @@ -430,10 +454,11 @@ public class DefaultPluginOperator implements PluginOperator { } try { String fileName = sourcePath.getFileName().toString(); - String targetName = integrationConfiguration.backupPath() + File.separator + getNowTimeByFormat(); - if(!StringUtils.isEmpty(appendName)){ - targetName = targetName + "_" + appendName; + String targetName = integrationConfiguration.backupPath() + File.separator; + if(!StringUtils.isEmpty(sign)){ + targetName = targetName + "[" + sign + "]"; } + targetName = targetName + "[" + getNowTimeByFormat() + "]"; Path target = Paths.get(targetName + "_" + fileName); if(!Files.exists(target.getParent())){ Files.createDirectories(target.getParent()); @@ -444,8 +469,9 @@ public class DefaultPluginOperator implements PluginOperator { // 源文件字节为0, 说明为删除的插件。不需要备份 return true; } - FileUtils.writeByteArrayToFile(targetFile, FileUtils.readFileToByteArray(sourceFile)); + FileUtils.copyFile(sourceFile, targetFile); if(type == 1){ + // 在运行期间由于文件无法被删除, 因此将该文件置为空文件, 在系统下次启动时会清除空文件的。 FileUtils.writeByteArrayToFile(sourceFile, "".getBytes()); } return true; diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java index 091b5fa..63abaa5 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java @@ -28,6 +28,7 @@ public interface PluginOperator { /** * 通过路径安装插件(会启用), 该插件文件必须存在于服务器 [适用于生产环境] + * 如果在插件目录存在同名的插件包(大小不为0k), 系统会自动备份该插件包。备份文件命名规则为;[install-backup][时间]_原jar名.jar * @param path 插件路径 * @return 成功返回true.不成功抛出异常或者返回false * @throws Exception 异常信息 @@ -37,6 +38,8 @@ public interface PluginOperator { /** * 卸载插件 [适用于生产环境] + * 卸载后, 会将该插件备份到备份目录, 备份文件命名规则为;[uninstall][时间]_原jar名.jar + * 在插件目录, 卸载的插件文件会变成0k. 这是正常的。在下次启动时, 程序会自动清除该文件。 * @param pluginId 插件id * @return 成功返回true.不成功抛出异常或者返回false * @throws Exception 异常信息 @@ -63,6 +66,7 @@ public interface PluginOperator { /** * 上传插件并启用插件。[适用于生产环境] + * 如果在插件目录存在同名的插件包(大小不为0k), 系统会自动备份该插件包。备份文件命名规则为;[install-backup][时间]_原jar名.jar * @param pluginFile 配置文件 * @return 成功返回true.不成功返回false, 或者抛出异常 * @throws Exception 异常信息 @@ -71,6 +75,7 @@ public interface PluginOperator { /** * 通过路径安装插件的配置文件。该文件必须存在于服务器。[适用于生产环境] + * 如果配置文件目录存在同名的配置文件, 系统会自动备份该配置文件。备份文件命名规则为;[install-config-backup][时间]_原jar名.jar * @param path 配置文件路径。 * @return 成功返回true.不成功返回false, 或者抛出异常 * @throws Exception @@ -79,7 +84,8 @@ public interface PluginOperator { /** - * 上传配置文件(如果存在, 则覆盖)。[适用于生产环境] + * 上传配置文件。[适用于生产环境] + * 如果配置文件目录存在同名的配置文件, 系统会自动备份该配置文件。备份文件命名规则为;[upload-config-backup][时间]_原jar名.jar * @param configFile 配置文件 * @return 成功返回true.不成功返回false, 或者抛出异常 * @throws Exception 异常信息 @@ -89,20 +95,20 @@ public interface PluginOperator { /** * 通过路径备份文件。可备份插件和插件的配置文件。[适用于生产环境] * @param path 路径 - * @param appendName 追加的名称 + * @param sign 备份文件的自定义标识 * @return 成功返回true.不成功返回false, 或者抛出异常 * @throws Exception 异常信息 */ - boolean backupPlugin(Path path, String appendName) throws Exception; + boolean backupPlugin(Path path, String sign) throws Exception; /** * 通过插件id备份插件。[适用于生产环境] * @param pluginId 插件id - * @param appendName 追加的名称 + * @param sign 备份文件的自定义标识 * @return 成功返回true.不成功返回false, 或者抛出异常 * @throws Exception 异常信息 */ - boolean backupPlugin(String pluginId, String appendName) throws Exception; + boolean backupPlugin(String pluginId, String sign) throws Exception; /** * 获取插件信息 [适用于生产环境、开发环境] diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/PluginUser.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/PluginUser.java index 37d25f8..52895fb 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/PluginUser.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/PluginUser.java @@ -4,7 +4,8 @@ import java.util.List; import java.util.Map; /** - * 插件使用者 + * 该接口用于在主程序操作Spring管理的插件bean. + * 主要用途: 在主程序定义接口。插件中实现该接口做扩展, 主程序通过接口class可以获取到插件中的实现类。 * @author zhangzhuo * @version 2.0.2 */ @@ -17,6 +18,7 @@ public interface PluginUser { * @return T */ T getBean(String name); + /** * 通过aClass得到bean。(Spring管理的bean) * @param aClass class @@ -36,6 +38,10 @@ public interface PluginUser { /** * 在主程序中定义的接口。 * 插件或者主程序实现该接口。可以该方法获取到实现该接口的所有实现类。(Spring管理的bean) + * 使用场景: + * 1. 在主程序定义接口 + * 2. 在主程序和插件包中都存在实现该接口, 并使用Spring的组件注解(@Component、@Service) + * 3. 使用该方法可以获取到所以实现该接口的实现类(主程序和插件中)。 * @param aClass 接口的类 * @param bean的类型 * @return List @@ -44,7 +50,10 @@ public interface PluginUser { /** * 得到主函数中定义的类。 - * 主程序实现该接口。可以该方法获取到实现该接口的所有实现类。(Spring管理的bean) + * 使用场景: + * 1. 在主程序定义接口 + * 2. 在主程序和插件包中都存在实现该接口, 并使用Spring的组件注解(@Component、@Service) + * 3. 使用该方法可以获取到主程序实现该接口的实现类。 * @param aClass 类/接口的类 * @param bean 的类型 * @return List @@ -54,6 +63,10 @@ public interface PluginUser { /** * 在主程序中定义的接口。获取插件中实现该接口的实现类。(Spring管理的bean) + * 使用场景: + * 1. 在主程序定义接口 + * 2. 插件包中实现该接口, 并使用Spring的组件注解(@Component、@Service) + * 3. 使用该方法可以获取到插件中实现该接口的实现类(不包括主程序)。 * @param aClass 接口的类 * @param bean的类型 * @return 实现 aClass 接口的实现类的集合 @@ -62,6 +75,10 @@ public interface PluginUser { /** * 在主程序中定义的接口。获取指定插件中实现该接口的实现类。(Spring管理的bean) + * 使用场景: + * 1. 在主程序定义接口 + * 2. 插件包中实现该接口, 并使用Spring的组件注解(@Component、@Service) + * 3. 使用该方法可以获取到指定插件中实现该接口的实现类。 * @param pluginId 插件id * @param aClass 接口的类 * @param bean的类型 @@ -70,7 +87,11 @@ public interface PluginUser { List getPluginBeans(String pluginId, Class aClass); /** - * 得到插件扩展接口实现的bean。(非Spring管理) + * 使用场景: + * 1. 在主程序定义接口(该接口需要继承 ExtensionPoint 接口)。 + * 2. 插件包中实现该接口 + * 3. 在主程序可以使用该方法获取到实现该接口的实现类。(实现类可以配合 @Extension 控制顺序) + * 注意: 该场景用于非Spring管理的bean, 使用Spring注解无效 * @param tClass bean的类型 * @param bean的类型 * @return List -- Gitee From c7edde139dcc2d3c3bed72dc41b49d94f913fca1 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Fri, 25 Oct 2019 15:06:26 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9B=86=E6=88=90?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...06\346\210\220\346\226\207\346\241\243.pdf" | Bin 0 -> 279740 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "doc/\351\233\206\346\210\220\346\226\207\346\241\243.pdf" diff --git "a/doc/\351\233\206\346\210\220\346\226\207\346\241\243.pdf" "b/doc/\351\233\206\346\210\220\346\226\207\346\241\243.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..6ae270090d5c0e28399c5ebb37903f4019e71d13 GIT binary patch literal 279740 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

piqxk`jRr1b?S0D3i(nzrrCaG_nJ*}@;U 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 z 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ό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 literal 0 HcmV?d00001 -- Gitee From 516d81ec93b50280e45f0eac8fe039644b26d46b Mon Sep 17 00:00:00 2001 From: StarBlues Date: Fri, 25 Oct 2019 15:08:03 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7a0ac81..475f355 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,11 @@ ### maven 仓库地址 -[https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework](https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework) +[https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework](https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework?_blank) ### 文档地址 -[https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages](https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages) +[https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages](https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages?_blank) ### QQ交流群 -- Gitee From b1f5380a3c9407c9642f95959473b73378b5f4a6 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Fri, 25 Oct 2019 15:09:20 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 475f355..7a0ac81 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,11 @@ ### maven 仓库地址 -[https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework](https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework?_blank) +[https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework](https://mvnrepository.com/artifact/com.gitee.starblues/springboot-plugin-framework) ### 文档地址 -[https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages](https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages?_blank) +[https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages](https://gitee.com/starblues/springboot-plugin-framework-parent/wikis/pages) ### QQ交流群 -- Gitee From 155dfdee30cb8ae8abe983182029171e4b18c266 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Sat, 26 Oct 2019 11:50:12 +0800 Subject: [PATCH 5/9] =?UTF-8?q?1.=20=E5=8D=87=E7=BA=A7pf4j=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=88=B03.1.0=202.=20=E4=BF=AE=E5=A4=8D=E5=8D=B8?= =?UTF-8?q?=E8=BD=BD=E5=90=8E=E6=97=A0=E6=B3=95=E5=88=A0=E9=99=A4=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=8C=85=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/main/config/PluginBeanConfig.java | 4 +- .../example/main/rest/PluginResource.java | 81 ++++++++++--------- .../basic/example/plugin1/DefinePlugin.java | 5 +- .../basic/example/plugin2/DefinePlugin.java | 5 +- .../mybatis/main/config/PluginBeanConfig.java | 7 +- .../com/mybatis/main/rest/PluginResource.java | 49 +++++++---- .../com/mybatis/plugin1/ExamplePlugin1.java | 5 +- .../com/mybatis/plugin2/ExamplePlugin2.java | 5 +- .../main/config/PluginBeanConfig.java | 4 +- .../mybatisplus/plugin/MybatisPlusPlugin.java | 5 +- .../mybatis/PluginMybatisXmlLoader.java | 12 ++- .../mybatis/PluginMybatisXmlProcessor.java | 12 +-- .../mybatis/utils/MybatisXmlProcess.java | 24 ++++-- springboot-plugin-framework/pom.xml | 3 +- .../AbstractConfigurationParser.java | 7 +- .../pipe/classs/PluginClassProcess.java | 7 +- .../DefaultIntegrationFactory.java | 10 ++- .../integration/IntegrationFactory.java | 4 +- .../operator/DefaultPluginOperator.java | 41 +++++----- .../integration/operator/PluginOperator.java | 11 ++- .../operator/verify/PluginLegalVerify.java | 16 ++-- .../operator/verify/PluginUploadVerify.java | 4 +- .../operator/verify/PluginVerify.java | 5 +- .../loader/PluginResourceLoadFactory.java | 55 ++++++++----- .../loader/PluginResourceLoader.java | 15 +++- .../starblues/loader/ResourceWrapper.java | 53 ++++++++++++ .../loader/load/PluginClassLoader.java | 12 ++- .../loader/load/PluginConfigFileLoader.java | 10 ++- .../gitee/starblues/realize/BasePlugin.java | 69 +++++++++------- 29 files changed, 342 insertions(+), 198 deletions(-) create mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java index 3c24ec2..72e4f9e 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java @@ -3,7 +3,6 @@ package com.basic.example.main.config; import com.gitee.starblues.integration.*; import com.gitee.starblues.integration.initialize.AutoPluginInitializer; import com.gitee.starblues.integration.initialize.PluginInitializer; -import org.pf4j.PluginException; import org.pf4j.PluginManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,10 +20,9 @@ public class PluginBeanConfig { * 通过默认的集成工厂返回 PluginManager * @param integrationConfiguration 集成的配置文件 * @return - * @throws PluginException */ @Bean - public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) throws PluginException { + public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) { IntegrationFactory integrationFactory = new DefaultIntegrationFactory(); return integrationFactory.getPluginManager(integrationConfiguration); } diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java index bb54179..2b6c367 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java @@ -27,7 +27,6 @@ public class PluginResource { public PluginResource(PluginApplication pluginApplication) { this.pluginOperator = pluginApplication.getPluginOperator(); } - /** * 获取插件信息 * @return 返回插件信息 @@ -60,8 +59,11 @@ public class PluginResource { @PostMapping("/stop/{id}") public String stop(@PathVariable("id") String id){ try { - pluginOperator.stop(id); - return "plugin '" + id +"' stop success"; + if(pluginOperator.stop(id)){ + return "plugin '" + id +"' stop success"; + } else { + return "plugin '" + id +"' stop failure"; + } } catch (Exception e) { e.printStackTrace(); return "plugin '" + id +"' stop failure. " + e.getMessage(); @@ -76,8 +78,11 @@ public class PluginResource { @PostMapping("/start/{id}") public String start(@PathVariable("id") String id){ try { - pluginOperator.start(id); - return "plugin '" + id +"' start success"; + if(pluginOperator.start(id)){ + return "plugin '" + id +"' start success"; + } else { + return "plugin '" + id +"' start failure"; + } } catch (Exception e) { e.printStackTrace(); return "plugin '" + id +"' start failure. " + e.getMessage(); @@ -93,8 +98,11 @@ public class PluginResource { @PostMapping("/uninstall/{id}") public String uninstall(@PathVariable("id") String id){ try { - pluginOperator.uninstall(id); - return "plugin '" + id +"' uninstall success"; + if(pluginOperator.uninstall(id, true)){ + return "plugin '" + id +"' uninstall success"; + } else { + return "plugin '" + id +"' uninstall failure"; + } } catch (Exception e) { e.printStackTrace(); return "plugin '" + id +"' uninstall failure. " + e.getMessage(); @@ -110,8 +118,11 @@ public class PluginResource { @PostMapping("/installByPath") public String install(@RequestParam("path") String path){ try { - pluginOperator.install(Paths.get(path)); - return "installByPath success"; + if(pluginOperator.install(Paths.get(path))){ + return "installByPath success"; + } else { + return "installByPath failure"; + } } catch (Exception e) { e.printStackTrace(); return "installByPath failure : " + e.getMessage(); @@ -127,8 +138,11 @@ public class PluginResource { @PostMapping("/uploadInstallPluginJar") public String install(@RequestParam("jarFile") MultipartFile multipartFile){ try { - pluginOperator.uploadPluginAndStart(multipartFile); - return "install success"; + if(pluginOperator.uploadPluginAndStart(multipartFile)){ + return "install success"; + } else { + return "install failure"; + } } catch (Exception e) { e.printStackTrace(); return "install failure : " + e.getMessage(); @@ -136,24 +150,6 @@ public class PluginResource { } - - /** - * 备份插件。注意: 该操作只适用于生产环境 - * @param pluginId 插件id - * @return 操作结果 - */ - @PostMapping("/back/{pluginId}") - public String backupPlugin(@PathVariable("pluginId") String pluginId){ - try { - pluginOperator.backupPlugin(pluginId, "testBack"); - return "backupPlugin success"; - } catch (Exception e) { - e.printStackTrace(); - return "backupPlugin failure : " + e.getMessage(); - } - } - - /** * 上传插件的配置文件。注意: 该操作只适用于生产环境 * @param multipartFile 上传文件 multipartFile @@ -162,27 +158,34 @@ public class PluginResource { @PostMapping("/uploadPluginConfigFile") public String uploadConfig(@RequestParam("configFile") MultipartFile multipartFile){ try { - pluginOperator.uploadConfigFile(multipartFile); - return "uploadPluginConfigFile success"; + if(pluginOperator.uploadConfigFile(multipartFile)){ + return "uploadConfig success"; + } else { + return "uploadConfig failure"; + } } catch (Exception e) { e.printStackTrace(); - return "uploadPluginConfigFile failure : " + e.getMessage(); + return "uploadConfig failure : " + e.getMessage(); } } + /** - * 通过路径安装配置文件。注意: 该操作只适用于生产环境 - * @param path 配置文件路径 + * 备份插件。注意: 该操作只适用于生产环境 + * @param pluginId 插件id * @return 操作结果 */ - @PostMapping("/installPluginConfig") - public String installPluginConfig(@RequestParam("path") String path){ + @PostMapping("/back/{pluginId}") + public String backupPlugin(@PathVariable("pluginId") String pluginId){ try { - pluginOperator.installConfigFile(Paths.get(path)); - return "installPluginConfig success"; + if(pluginOperator.backupPlugin(pluginId, "testBack")){ + return "backupPlugin success"; + } else { + return "backupPlugin failure"; + } } catch (Exception e) { e.printStackTrace(); - return "installPluginConfig failure : " + e.getMessage(); + return "backupPlugin failure : " + e.getMessage(); } } diff --git a/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/DefinePlugin.java b/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/DefinePlugin.java index 4c45db8..da0f380 100644 --- a/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/DefinePlugin.java +++ b/example/basic-example/plugins/basic-example-plugin1/src/main/java/com/basic/example/plugin1/DefinePlugin.java @@ -1,7 +1,6 @@ package com.basic.example.plugin1; import com.gitee.starblues.realize.BasePlugin; -import org.pf4j.PluginException; import org.pf4j.PluginWrapper; /** @@ -16,12 +15,12 @@ public class DefinePlugin extends BasePlugin { } @Override - protected void startEvent() throws PluginException { + protected void startEvent() { } @Override - protected void deleteEvent() throws PluginException { + protected void deleteEvent() { } diff --git a/example/basic-example/plugins/basic-example-plugin2/src/main/java/com/basic/example/plugin2/DefinePlugin.java b/example/basic-example/plugins/basic-example-plugin2/src/main/java/com/basic/example/plugin2/DefinePlugin.java index 794445d..98f258b 100644 --- a/example/basic-example/plugins/basic-example-plugin2/src/main/java/com/basic/example/plugin2/DefinePlugin.java +++ b/example/basic-example/plugins/basic-example-plugin2/src/main/java/com/basic/example/plugin2/DefinePlugin.java @@ -1,7 +1,6 @@ package com.basic.example.plugin2; import com.gitee.starblues.realize.BasePlugin; -import org.pf4j.PluginException; import org.pf4j.PluginWrapper; /** @@ -16,12 +15,12 @@ public class DefinePlugin extends BasePlugin { } @Override - protected void startEvent() throws PluginException { + protected void startEvent() { } @Override - protected void deleteEvent() throws PluginException { + protected void deleteEvent() { } diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java index 2acb949..4fd7c90 100644 --- a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java +++ b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java @@ -4,7 +4,6 @@ import com.gitee.starblues.extension.mybatis.SpringBootMybatisExtension; import com.gitee.starblues.integration.*; import com.gitee.starblues.integration.initialize.AutoPluginInitializer; import com.gitee.starblues.integration.initialize.PluginInitializer; -import org.pf4j.PluginException; import org.pf4j.PluginManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -23,11 +22,11 @@ public class PluginBeanConfig { /** * 通过默认的集成工厂返回 PluginManager * @param integrationConfiguration 集成的配置文件 - * @return - * @throws PluginException + * @return PluginManager + * @throws Exception */ @Bean - public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) throws PluginException { + public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) { IntegrationFactory integrationFactory = new DefaultIntegrationFactory(); return integrationFactory.getPluginManager(integrationConfiguration); } diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java index 917e33b..6f67fea 100644 --- a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java +++ b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java @@ -61,8 +61,11 @@ public class PluginResource { @PostMapping("/stop/{id}") public String stop(@PathVariable("id") String id){ try { - pluginOperator.stop(id); - return "plugin '" + id +"' stop success"; + if(pluginOperator.stop(id)){ + return "plugin '" + id +"' stop success"; + } else { + return "plugin '" + id +"' stop failure"; + } } catch (Exception e) { e.printStackTrace(); return "plugin '" + id +"' stop failure. " + e.getMessage(); @@ -77,8 +80,11 @@ public class PluginResource { @PostMapping("/start/{id}") public String start(@PathVariable("id") String id){ try { - pluginOperator.start(id); - return "plugin '" + id +"' start success"; + if(pluginOperator.start(id)){ + return "plugin '" + id +"' start success"; + } else { + return "plugin '" + id +"' start failure"; + } } catch (Exception e) { e.printStackTrace(); return "plugin '" + id +"' start failure. " + e.getMessage(); @@ -94,8 +100,11 @@ public class PluginResource { @PostMapping("/uninstall/{id}") public String uninstall(@PathVariable("id") String id){ try { - pluginOperator.uninstall(id); - return "plugin '" + id +"' uninstall success"; + if(pluginOperator.uninstall(id, true)){ + return "plugin '" + id +"' uninstall success"; + } else { + return "plugin '" + id +"' uninstall failure"; + } } catch (Exception e) { e.printStackTrace(); return "plugin '" + id +"' uninstall failure. " + e.getMessage(); @@ -111,8 +120,11 @@ public class PluginResource { @PostMapping("/installByPath") public String install(@RequestParam("path") String path){ try { - pluginOperator.install(Paths.get(path)); - return "installByPath success"; + if(pluginOperator.install(Paths.get(path))){ + return "installByPath success"; + } else { + return "installByPath failure"; + } } catch (Exception e) { e.printStackTrace(); return "installByPath failure : " + e.getMessage(); @@ -128,8 +140,11 @@ public class PluginResource { @PostMapping("/uploadInstallPluginJar") public String install(@RequestParam("jarFile") MultipartFile multipartFile){ try { - pluginOperator.uploadPluginAndStart(multipartFile); - return "install success"; + if(pluginOperator.uploadPluginAndStart(multipartFile)){ + return "install success"; + } else { + return "install failure"; + } } catch (Exception e) { e.printStackTrace(); return "install failure : " + e.getMessage(); @@ -145,8 +160,11 @@ public class PluginResource { @PostMapping("/uploadPluginConfigFile") public String uploadConfig(@RequestParam("configFile") MultipartFile multipartFile){ try { - pluginOperator.uploadConfigFile(multipartFile); - return "uploadConfig success"; + if(pluginOperator.uploadConfigFile(multipartFile)){ + return "uploadConfig success"; + } else { + return "uploadConfig failure"; + } } catch (Exception e) { e.printStackTrace(); return "uploadConfig failure : " + e.getMessage(); @@ -162,8 +180,11 @@ public class PluginResource { @PostMapping("/back/{pluginId}") public String backupPlugin(@PathVariable("pluginId") String pluginId){ try { - pluginOperator.backupPlugin(pluginId, "testBack"); - return "backupPlugin success"; + if(pluginOperator.backupPlugin(pluginId, "testBack")){ + return "backupPlugin success"; + } else { + return "backupPlugin failure"; + } } catch (Exception e) { e.printStackTrace(); return "backupPlugin failure : " + e.getMessage(); diff --git a/example/integration-mybatis/plugins/integration-mybatis-plugin1/src/main/java/com/mybatis/plugin1/ExamplePlugin1.java b/example/integration-mybatis/plugins/integration-mybatis-plugin1/src/main/java/com/mybatis/plugin1/ExamplePlugin1.java index 3e65cf4..d541643 100644 --- a/example/integration-mybatis/plugins/integration-mybatis-plugin1/src/main/java/com/mybatis/plugin1/ExamplePlugin1.java +++ b/example/integration-mybatis/plugins/integration-mybatis-plugin1/src/main/java/com/mybatis/plugin1/ExamplePlugin1.java @@ -2,7 +2,6 @@ package com.mybatis.plugin1; import com.gitee.starblues.extension.mybatis.configuration.SpringBootMybatisConfig; import com.gitee.starblues.realize.BasePlugin; -import org.pf4j.PluginException; import org.pf4j.PluginWrapper; import java.util.HashSet; @@ -25,12 +24,12 @@ public class ExamplePlugin1 extends BasePlugin implements SpringBootMybatisConfi } @Override - protected void startEvent() throws PluginException { + protected void startEvent() { } @Override - protected void deleteEvent() throws PluginException { + protected void deleteEvent() { } diff --git a/example/integration-mybatis/plugins/integration-mybatis-plugin2/src/main/java/com/mybatis/plugin2/ExamplePlugin2.java b/example/integration-mybatis/plugins/integration-mybatis-plugin2/src/main/java/com/mybatis/plugin2/ExamplePlugin2.java index b1faef5..da63749 100644 --- a/example/integration-mybatis/plugins/integration-mybatis-plugin2/src/main/java/com/mybatis/plugin2/ExamplePlugin2.java +++ b/example/integration-mybatis/plugins/integration-mybatis-plugin2/src/main/java/com/mybatis/plugin2/ExamplePlugin2.java @@ -2,7 +2,6 @@ package com.mybatis.plugin2; import com.gitee.starblues.extension.mybatis.configuration.SpringBootMybatisConfig; import com.gitee.starblues.realize.BasePlugin; -import org.pf4j.PluginException; import org.pf4j.PluginWrapper; import java.util.HashSet; @@ -25,12 +24,12 @@ public class ExamplePlugin2 extends BasePlugin implements SpringBootMybatisConfi } @Override - protected void startEvent() throws PluginException { + protected void startEvent() { } @Override - protected void deleteEvent() throws PluginException { + protected void deleteEvent() { } diff --git a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java index 735e548..3d74552 100644 --- a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java +++ b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java @@ -4,7 +4,6 @@ import com.gitee.starblues.extension.mybatis.SpringBootMybatisExtension; import com.gitee.starblues.integration.*; import com.gitee.starblues.integration.initialize.AutoPluginInitializer; import com.gitee.starblues.integration.initialize.PluginInitializer; -import org.pf4j.PluginException; import org.pf4j.PluginManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -24,10 +23,9 @@ public class PluginBeanConfig { * 通过默认的集成工厂返回 PluginManager * @param integrationConfiguration 集成的配置文件 * @return - * @throws PluginException */ @Bean - public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) throws PluginException { + public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) { IntegrationFactory integrationFactory = new DefaultIntegrationFactory(); return integrationFactory.getPluginManager(integrationConfiguration); } diff --git a/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/src/main/java/com/mybatisplus/plugin/MybatisPlusPlugin.java b/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/src/main/java/com/mybatisplus/plugin/MybatisPlusPlugin.java index 4909709..dc8bb40 100644 --- a/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/src/main/java/com/mybatisplus/plugin/MybatisPlusPlugin.java +++ b/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/src/main/java/com/mybatisplus/plugin/MybatisPlusPlugin.java @@ -2,7 +2,6 @@ package com.mybatisplus.plugin; import com.gitee.starblues.extension.mybatis.configuration.SpringBootMybatisConfig; import com.gitee.starblues.realize.BasePlugin; -import org.pf4j.PluginException; import org.pf4j.PluginWrapper; import java.util.HashSet; @@ -25,12 +24,12 @@ public class MybatisPlusPlugin extends BasePlugin implements SpringBootMybatisCo } @Override - protected void startEvent() throws PluginException { + protected void startEvent() { } @Override - protected void deleteEvent() throws PluginException { + protected void deleteEvent() { } diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java index 53978ed..6d2fb12 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java @@ -2,6 +2,7 @@ package com.gitee.starblues.extension.mybatis; import com.gitee.starblues.extension.mybatis.configuration.SpringBootMybatisConfig; import com.gitee.starblues.loader.PluginResourceLoader; +import com.gitee.starblues.loader.ResourceWrapper; import com.gitee.starblues.realize.BasePlugin; import com.gitee.starblues.utils.OrderExecution; import com.gitee.starblues.utils.OrderPriority; @@ -42,7 +43,7 @@ public class PluginMybatisXmlLoader implements PluginResourceLoader { } @Override - public List load(BasePlugin basePlugin) throws Exception { + public ResourceWrapper load(BasePlugin basePlugin) throws Exception { if(!(basePlugin instanceof SpringBootMybatisConfig)){ LOG.warn("Plugin <{}> not implements SpringBootMybatisConfig, If you need to use mybatis in the plugin," + "Please implements SpringBootMybatisConfig interface", basePlugin.getClass().getName()); @@ -53,7 +54,7 @@ public class PluginMybatisXmlLoader implements PluginResourceLoader { if(mybatisMapperXmlLocationsMatch == null || mybatisMapperXmlLocationsMatch.isEmpty()){ LOG.warn("SpringBootMybatisConfig -> mybatisMapperXmlLocationsMatch return is empty, " + "Please check configuration"); - return Collections.emptyList(); + return new ResourceWrapper(); } ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(basePlugin.getWrapper().getPluginClassLoader()); @@ -67,7 +68,12 @@ public class PluginMybatisXmlLoader implements PluginResourceLoader { resources.addAll(loadResources); } } - return resources; + return new ResourceWrapper(resources); + } + + @Override + public void unload(BasePlugin basePlugin, ResourceWrapper resourceWrapper) throws Exception { + // } @Override diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java index 0bd6110..bb033e6 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java @@ -1,6 +1,7 @@ package com.gitee.starblues.extension.mybatis; import com.gitee.starblues.extension.mybatis.utils.MybatisXmlProcess; +import com.gitee.starblues.loader.ResourceWrapper; import com.gitee.starblues.realize.BasePlugin; import com.gitee.starblues.factory.PluginRegistryInfo; import com.gitee.starblues.factory.process.pipe.PluginPipeProcessorExtend; @@ -48,15 +49,16 @@ public class PluginMybatisXmlProcessor implements PluginPipeProcessorExtend { } BasePlugin basePlugin = pluginRegistryInfo.getBasePlugin(); PluginWrapper pluginWrapper = pluginRegistryInfo.getPluginWrapper(); - List pluginResources = + ResourceWrapper resourceWrapper = basePlugin.getPluginResourceLoadFactory().getPluginResources(PluginMybatisXmlLoader.KEY); - if(pluginResources == null || pluginResources.isEmpty()){ + if(resourceWrapper == null){ return; } - boolean change = mybatisXmlProcess.isChange(pluginResources); - if(change){ - mybatisXmlProcess.loadXmlResource(pluginResources, pluginWrapper.getPluginClassLoader()); + List pluginResources = resourceWrapper.getResources(); + if(pluginResources == null || pluginResources.isEmpty()){ + return; } + mybatisXmlProcess.loadXmlResource(pluginResources, pluginWrapper.getPluginClassLoader()); } @Override diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java index 7fc96fd..4e06e1a 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java @@ -7,6 +7,7 @@ import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.core.io.Resource; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; import java.util.List; import java.util.Map; @@ -62,17 +63,25 @@ public class MybatisXmlProcess { return; } Configuration configuration = factory.getConfiguration(); - //removeConfig(configuration); + // removeConfig(configuration); ClassLoader defaultClassLoader = Resources.getDefaultClassLoader(); try { Resources.setDefaultClassLoader(pluginClassLoader); for (Resource resource :resources) { - PluginMybatisXmlMapperBuilder xmlMapperBuilder = new PluginMybatisXmlMapperBuilder( - resource.getInputStream(), - configuration, resource.toString(), - configuration.getSqlFragments(), - pluginClassLoader); - xmlMapperBuilder.parse(); + InputStream inputStream = resource.getInputStream(); + try { + PluginMybatisXmlMapperBuilder xmlMapperBuilder = new PluginMybatisXmlMapperBuilder( + inputStream, + configuration, resource.toString(), + configuration.getSqlFragments(), + pluginClassLoader); + xmlMapperBuilder.parse(); + } finally { + if(inputStream != null){ + inputStream.close(); + } + } + } } finally { ErrorContext.instance().reset(); @@ -86,6 +95,7 @@ public class MybatisXmlProcess { * @return boolean * @throws IOException IOException */ + @Deprecated public boolean isChange(List resources) throws IOException { if(resources == null || resources.isEmpty()){ return false; diff --git a/springboot-plugin-framework/pom.xml b/springboot-plugin-framework/pom.xml index 1de711c..15a78cc 100644 --- a/springboot-plugin-framework/pom.xml +++ b/springboot-plugin-framework/pom.xml @@ -64,8 +64,7 @@ 3.1.0 1.6 - 2.6.0 - 2.0.0 + 3.1.0 5.1.7.RELEASE 2.9.9 diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/bean/configuration/AbstractConfigurationParser.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/bean/configuration/AbstractConfigurationParser.java index 3634ebb..c82c8fa 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/bean/configuration/AbstractConfigurationParser.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/bean/configuration/AbstractConfigurationParser.java @@ -2,6 +2,7 @@ package com.gitee.starblues.factory.process.pipe.bean.configuration; import com.gitee.starblues.integration.IntegrationConfiguration; import com.gitee.starblues.loader.PluginResourceLoader; +import com.gitee.starblues.loader.ResourceWrapper; import com.gitee.starblues.loader.load.PluginConfigFileLoader; import com.gitee.starblues.realize.BasePlugin; import org.springframework.core.io.Resource; @@ -41,7 +42,11 @@ public abstract class AbstractConfigurationParser implements ConfigurationParser fileName, configuration.environment() ); - List resources = pluginResourceLoader.load(basePlugin); + ResourceWrapper resourceWrapper = pluginResourceLoader.load(basePlugin); + if(resourceWrapper == null){ + return null; + } + List resources = resourceWrapper.getResources(); if(resources.isEmpty() || resources.size() != 1){ return null; } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/classs/PluginClassProcess.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/classs/PluginClassProcess.java index 45c2215..ae2774c 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/classs/PluginClassProcess.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/process/pipe/classs/PluginClassProcess.java @@ -5,6 +5,7 @@ import com.gitee.starblues.factory.PluginRegistryInfo; import com.gitee.starblues.factory.process.pipe.PluginPipeProcessor; import com.gitee.starblues.factory.process.pipe.classs.group.*; import com.gitee.starblues.loader.PluginResourceLoadFactory; +import com.gitee.starblues.loader.ResourceWrapper; import com.gitee.starblues.loader.load.PluginClassLoader; import com.gitee.starblues.realize.BasePlugin; import org.slf4j.Logger; @@ -68,7 +69,11 @@ public class PluginClassProcess implements PluginPipeProcessor { public void registry(PluginRegistryInfo pluginRegistryInfo) throws Exception { BasePlugin basePlugin = pluginRegistryInfo.getBasePlugin(); PluginResourceLoadFactory pluginResourceLoadFactory = basePlugin.getPluginResourceLoadFactory(); - List pluginResources = pluginResourceLoadFactory.getPluginResources(PluginClassLoader.KEY); + ResourceWrapper resourceWrapper = pluginResourceLoadFactory.getPluginResources(PluginClassLoader.KEY); + if(resourceWrapper == null){ + return; + } + List pluginResources = resourceWrapper.getResources(); if(pluginResources == null){ return; } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java index 94c2833..50cc15a 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java @@ -14,12 +14,14 @@ import java.util.Objects; public class DefaultIntegrationFactory implements IntegrationFactory { - @Override - public PluginManager getPluginManager(IntegrationConfiguration configuration) throws PluginException { + public PluginManager getPluginManager(IntegrationConfiguration configuration) { + if(configuration == null){ + throw new NullPointerException("IntegrationConfiguration is null"); + } RuntimeMode environment = configuration.environment(); if(environment == null){ - throw new PluginException("Run environment can is null" + configuration.environment()); + throw new RuntimeException("Configuration RuntimeMode is null" + configuration.environment()); } if(RuntimeMode.DEVELOPMENT == environment){ // 开发环境下的插件管理者 @@ -42,7 +44,7 @@ public class DefaultIntegrationFactory implements IntegrationFactory { } }; } else { - throw new PluginException("Not found run environment " + configuration.environment()); + throw new RuntimeException("Not found run environment " + configuration.environment()); } } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java index f2f8d5b..92165db 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java @@ -1,6 +1,5 @@ package com.gitee.starblues.integration; -import org.pf4j.PluginException; import org.pf4j.PluginManager; /** @@ -15,8 +14,7 @@ public interface IntegrationFactory { * 得到插件管理者 * @param configuration 插件配置 * @return 插件管理者 - * @throws PluginException 插件异常 */ - PluginManager getPluginManager(IntegrationConfiguration configuration) throws PluginException; + PluginManager getPluginManager(IntegrationConfiguration configuration); } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index 8a0d102..0b157cd 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -147,7 +147,7 @@ public class DefaultPluginOperator implements PluginOperator { log.error("Install plugin '{}' failure. {}", pluginId, e.getMessage()); log.info("Start uninstall plugin '{}' failure", pluginId); try { - uninstall(pluginId); + uninstall(pluginId, false); } catch (Exception uninstallException){ log.error("Uninstall plugin '{}' failure. {}", pluginId, e.getMessage()); } @@ -160,11 +160,10 @@ public class DefaultPluginOperator implements PluginOperator { } @Override - public boolean uninstall(String pluginId) throws Exception { + public boolean uninstall(String pluginId, boolean isBackup) throws Exception { PluginWrapper pluginWrapper = pluginManager.getPlugin(pluginId); if(pluginWrapper == null){ - log.error("Uninstall plugin failure, Not found plugin '{}'", pluginId); - return false; + throw new Exception("Uninstall plugin failure, Not found plugin ''" + pluginId + "'"); } Exception exception = null; try { @@ -175,9 +174,11 @@ public class DefaultPluginOperator implements PluginOperator { exception = e; } try { - if (pluginManager.unloadPlugin(pluginId)) { - // 卸载完后,将插件文件移到备份文件中 + if(isBackup){ + // 将插件文件移到备份文件中 backup(pluginWrapper.getPluginPath(), "uninstall", 1); + } + if (pluginManager.deletePlugin(pluginId)) { log.info("Uninstall plugin '{}' success", pluginId); return true; } else { @@ -442,17 +443,20 @@ public class DefaultPluginOperator implements PluginOperator { * @param sign 文件标志 * @param type 类型 1移动 2拷贝 * @return 结果 - * @throws Exception Exception */ - private boolean backup(Path sourcePath, String sign, int type) throws Exception { - if(isDev()){ - // 如果是开发环境, 则不进行备份 - return true; - } - if(!Files.exists(sourcePath)){ - throw new FileNotFoundException("path ' " + sourcePath.toString() + "' does not exist!"); - } + private boolean backup(Path sourcePath, String sign, int type) { try { + if(isDev()){ + // 如果是开发环境, 则不进行备份 + return false; + } + if(sourcePath == null){ + return false; + } + if(!Files.exists(sourcePath)){ + log.error("path '{}' does not exist", sourcePath.toString()); + return false; + } String fileName = sourcePath.getFileName().toString(); String targetName = integrationConfiguration.backupPath() + File.separator; if(!StringUtils.isEmpty(sign)){ @@ -471,12 +475,13 @@ public class DefaultPluginOperator implements PluginOperator { } FileUtils.copyFile(sourceFile, targetFile); if(type == 1){ - // 在运行期间由于文件无法被删除, 因此将该文件置为空文件, 在系统下次启动时会清除空文件的。 - FileUtils.writeByteArrayToFile(sourceFile, "".getBytes()); + // 是移动的话, 则删除源文件 + FileUtils.deleteQuietly(sourceFile); } return true; } catch (IOException e) { - throw new Exception("Backup plugin jar '" + sourcePath.toString() + "' failure : " + e.getMessage(), e); + log.error("Backup plugin jar '{}' failure. {}", sourcePath.toString(), e.getMessage(), e); + return false; } } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java index 63abaa5..3fbc42d 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java @@ -28,7 +28,7 @@ public interface PluginOperator { /** * 通过路径安装插件(会启用), 该插件文件必须存在于服务器 [适用于生产环境] - * 如果在插件目录存在同名的插件包(大小不为0k), 系统会自动备份该插件包。备份文件命名规则为;[install-backup][时间]_原jar名.jar + * 如果在插件目录存在同名的插件包, 系统会自动备份该插件包。备份文件命名规则为;[install-backup][时间]_原jar名.jar * @param path 插件路径 * @return 成功返回true.不成功抛出异常或者返回false * @throws Exception 异常信息 @@ -38,13 +38,12 @@ public interface PluginOperator { /** * 卸载插件 [适用于生产环境] - * 卸载后, 会将该插件备份到备份目录, 备份文件命名规则为;[uninstall][时间]_原jar名.jar - * 在插件目录, 卸载的插件文件会变成0k. 这是正常的。在下次启动时, 程序会自动清除该文件。 * @param pluginId 插件id + * @param isBackup 是否备份原来的插件。备份文件命名规则为;[uninstall][时间]_原jar名.jar * @return 成功返回true.不成功抛出异常或者返回false * @throws Exception 异常信息 */ - boolean uninstall(String pluginId) throws Exception; + boolean uninstall(String pluginId, boolean isBackup) throws Exception; /** * 启用插件 [适用于生产环境、开发环境] @@ -66,7 +65,7 @@ public interface PluginOperator { /** * 上传插件并启用插件。[适用于生产环境] - * 如果在插件目录存在同名的插件包(大小不为0k), 系统会自动备份该插件包。备份文件命名规则为;[install-backup][时间]_原jar名.jar + * 如果在插件目录存在同名的插件包, 系统会自动备份该插件包。备份文件命名规则为;[install-backup][时间]_原jar名.jar * @param pluginFile 配置文件 * @return 成功返回true.不成功返回false, 或者抛出异常 * @throws Exception 异常信息 @@ -78,7 +77,7 @@ public interface PluginOperator { * 如果配置文件目录存在同名的配置文件, 系统会自动备份该配置文件。备份文件命名规则为;[install-config-backup][时间]_原jar名.jar * @param path 配置文件路径。 * @return 成功返回true.不成功返回false, 或者抛出异常 - * @throws Exception + * @throws Exception 安装异常 */ boolean installConfigFile(Path path) throws Exception; diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginLegalVerify.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginLegalVerify.java index d23cba7..f7fa541 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginLegalVerify.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginLegalVerify.java @@ -22,23 +22,23 @@ public class PluginLegalVerify implements PluginVerify{ @Override - public Path verify(Path path) throws PluginException { + public Path verify(Path path) throws Exception { if(path == null){ - throw new PluginException("path can not be null"); + throw new IllegalArgumentException("path can not be null"); } if(!pluginDescriptorFinder.isApplicable(path)){ // 插件包不合法 - throw new PluginException(path.toString() + " : plugin illegal"); + throw new Exception(path.toString() + " : plugin illegal"); } PluginDescriptor pluginDescriptor = pluginDescriptorFinder.find(path); if(pluginDescriptor == null){ - throw new PluginException(path.toString() + " : Not found Plugin Descriptor"); + throw new Exception(path.toString() + " : Not found Plugin Descriptor"); } if(StringUtils.isEmpty(pluginDescriptor.getPluginId())){ - throw new PluginException(path.toString() + " : Not found Plugin Id"); + throw new Exception(path.toString() + " : Not found Plugin Id"); } if(StringUtils.isEmpty(pluginDescriptor.getPluginClass())){ - throw new PluginException(path.toString() + " : Not found Plugin Class"); + throw new Exception(path.toString() + " : Not found Plugin Class"); } return postVerify(path, pluginDescriptor); } @@ -48,9 +48,9 @@ public class PluginLegalVerify implements PluginVerify{ * @param path 路径 * @param pluginDescriptor 插件解析者 * @return 返回路径 - * @throws PluginException 插件异常 + * @throws Exception 插件异常 */ - protected Path postVerify(Path path, PluginDescriptor pluginDescriptor) throws PluginException{ + protected Path postVerify(Path path, PluginDescriptor pluginDescriptor) throws Exception{ return path; } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginUploadVerify.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginUploadVerify.java index a8b79cd..7f3ea59 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginUploadVerify.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginUploadVerify.java @@ -23,7 +23,7 @@ public class PluginUploadVerify extends PluginLegalVerify{ @Override - protected Path postVerify(Path path, PluginDescriptor pluginDescriptor) throws PluginException { + protected Path postVerify(Path path, PluginDescriptor pluginDescriptor) throws Exception { PluginWrapper pluginWrapper = pluginManager.getPlugin(pluginDescriptor.getPluginId()); if(pluginWrapper == null){ // 当前没有该插件包运行 @@ -36,6 +36,6 @@ public class PluginUploadVerify extends PluginLegalVerify{ .append("> ; version <").append(runPluginDescriptor.getVersion()) .append("> ) is already exist in the current environment。 ") .append("Please uninstall the plugin, then upload and update the plugin"); - throw new PluginException(errorMsg.toString()); + throw new Exception(errorMsg.toString()); } } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginVerify.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginVerify.java index c63bdca..fcd967f 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginVerify.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/verify/PluginVerify.java @@ -1,6 +1,5 @@ package com.gitee.starblues.integration.operator.verify; -import org.pf4j.PluginException; import java.nio.file.Path; @@ -17,8 +16,8 @@ public interface PluginVerify { * 校验插件包 * @param path 插件路径 * @return 返回校验成功的路径 - * @throws PluginException 插件异常 + * @throws Exception 插件异常 */ - Path verify(Path path) throws PluginException; + Path verify(Path path) throws Exception; } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java index d715bce..62472e0 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java @@ -1,15 +1,12 @@ package com.gitee.starblues.loader; -import com.gitee.starblues.extension.AbstractExtension; import com.gitee.starblues.extension.ExtensionFactory; import com.gitee.starblues.loader.load.PluginClassLoader; import com.gitee.starblues.realize.BasePlugin; import com.gitee.starblues.utils.CommonUtils; import com.gitee.starblues.utils.OrderPriority; -import org.pf4j.PluginException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.io.Resource; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -27,7 +24,7 @@ public class PluginResourceLoadFactory { private static final Logger LOG = LoggerFactory.getLogger(PluginResourceLoadFactory.class); - private final Map> pluginResourceMap = new ConcurrentHashMap<>(); + private final Map pluginResourceWrappers = new ConcurrentHashMap<>(); private final List pluginResourceLoaders = new ArrayList<>(5); @@ -58,16 +55,15 @@ public class PluginResourceLoadFactory { }); } - - - /** * 加载插件类 - * @param basePlugin basePlugin - * @throws PluginException PluginException + * @param basePlugin 当前插件信息 */ - public synchronized void load(BasePlugin basePlugin) throws PluginException { + public synchronized void load(BasePlugin basePlugin) { for (PluginResourceLoader pluginResourceLoader : pluginResourceLoaders) { + if(pluginResourceLoader == null){ + continue; + } String key = pluginResourceLoader.key(); if(StringUtils.isEmpty(key)){ LOG.error("pluginResourceLoader {} key is empty, skip!", @@ -75,24 +71,45 @@ public class PluginResourceLoadFactory { continue; } try { - List resources = pluginResourceLoader.load(basePlugin); - if(resources != null){ - pluginResourceMap.put(key, resources); + ResourceWrapper resourceWrapper = pluginResourceLoader.load(basePlugin); + if(resourceWrapper != null){ + pluginResourceWrappers.put(key, resourceWrapper); } - } catch (Exception e) { - e.printStackTrace(); - throw new PluginException(e.getMessage()); + } catch (Exception e){ + LOG.error("Plugin resource loader '{}' load error. {}", key, e.getMessage(), e); } + } } + /** + * 卸载加载者加载的资源 + * @param basePlugin 当前插件信息 + */ + public synchronized void unload(BasePlugin basePlugin) { + for (PluginResourceLoader pluginResourceLoader : pluginResourceLoaders) { + if(pluginResourceLoader == null){ + continue; + } + String key = pluginResourceLoader.key(); + try { + ResourceWrapper resourceWrapper = pluginResourceWrappers.get(key); + pluginResourceLoader.unload(basePlugin, resourceWrapper); + } catch (Exception e){ + LOG.error("Plugin resource loader '{}' unload error. {}", key, e.getMessage(), e); + } + } + } + + + /** * 根据资源加载者的key获取插件资源 * @param key key - * @return List + * @return ResourceWrapper */ - public List getPluginResources(String key) { - return pluginResourceMap.get(key); + public ResourceWrapper getPluginResources(String key) { + return pluginResourceWrappers.get(key); } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java index 21aac94..372d179 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java @@ -23,11 +23,20 @@ public interface PluginResourceLoader { /** * 加载资源 - * @param basePlugin basePlugin - * @return List + * @param basePlugin 插件对象 + * @return 资源包装对象 * @throws Exception Exception */ - List load(BasePlugin basePlugin) throws Exception; + ResourceWrapper load(BasePlugin basePlugin) throws Exception; + + /** + * 卸载时的操作 + * @param basePlugin 插件对象 + * @param resourceWrapper 资源包装者 + * @throws Exception 卸载异常 + */ + void unload(BasePlugin basePlugin, ResourceWrapper resourceWrapper) throws Exception; + /** * 执行顺序 diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java new file mode 100644 index 0000000..1bc0b38 --- /dev/null +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java @@ -0,0 +1,53 @@ +package com.gitee.starblues.loader; + +import org.springframework.core.io.Resource; + +import java.util.*; + +/** + * 资源包装类 + * + * @author zhangzhuo + * @version 1.0 + */ +public class ResourceWrapper { + + private final List resources; + private final Map extensions = new HashMap<>(); + + + public ResourceWrapper() { + this.resources = new ArrayList<>(0); + } + + public ResourceWrapper(List resources) { + if(resources == null){ + this.resources = new ArrayList<>(0); + } else { + this.resources = resources; + } + } + + public ResourceWrapper(Resource[] resources) { + if(resources != null){ + this.resources = Arrays.asList(resources); + } else { + this.resources = new ArrayList<>(0); + } + } + + public List getResources(){ + return resources; + } + + + public void addExtension(String key, Object value) { + extensions.put(key, value); + } + + public Object getExtension(String key){ + return extensions.get(key); + } + + +} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java index 08b1efe..a742309 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java @@ -1,6 +1,7 @@ package com.gitee.starblues.loader.load; import com.gitee.starblues.loader.PluginResourceLoader; +import com.gitee.starblues.loader.ResourceWrapper; import com.gitee.starblues.realize.BasePlugin; import com.gitee.starblues.utils.OrderExecution; import com.gitee.starblues.utils.OrderPriority; @@ -29,7 +30,7 @@ public class PluginClassLoader implements PluginResourceLoader { } @Override - public List load(BasePlugin basePlugin) throws Exception{ + public ResourceWrapper load(BasePlugin basePlugin) throws Exception{ String scanPackage = basePlugin.scanPackage(); String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(scanPackage) + @@ -38,9 +39,14 @@ public class PluginClassLoader implements PluginResourceLoader { new PathMatchingResourcePatternResolver(basePlugin.getWrapper().getPluginClassLoader()); Resource[] resources = resourcePatternResolver.getResources(packageSearchPath); if(resources == null){ - return Collections.emptyList(); + return new ResourceWrapper(); } - return Arrays.asList(resources); + return new ResourceWrapper(resources); + } + + @Override + public void unload(BasePlugin basePlugin, ResourceWrapper resourceWrapper) throws Exception { + // Do nothing } @Override diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java index cf46718..04219ce 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java @@ -1,6 +1,7 @@ package com.gitee.starblues.loader.load; import com.gitee.starblues.loader.PluginResourceLoader; +import com.gitee.starblues.loader.ResourceWrapper; import com.gitee.starblues.realize.BasePlugin; import com.gitee.starblues.utils.OrderExecution; import com.gitee.starblues.utils.OrderPriority; @@ -40,7 +41,7 @@ public class PluginConfigFileLoader implements PluginResourceLoader { } @Override - public List load(BasePlugin basePlugin) throws Exception { + public ResourceWrapper load(BasePlugin basePlugin) throws Exception { Resource resource; if(runtimeMode == RuntimeMode.DEVELOPMENT){ // 开发环境下 @@ -54,7 +55,12 @@ public class PluginConfigFileLoader implements PluginResourceLoader { } List resources = new ArrayList<>(); resources.add(resource); - return resources; + return new ResourceWrapper(resources); + } + + @Override + public void unload(BasePlugin basePlugin, ResourceWrapper resourceWrapper) throws Exception { + // Do nothing } @Override diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java index 0d1e891..4ffd226 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java @@ -2,7 +2,6 @@ package com.gitee.starblues.realize; import com.gitee.starblues.loader.PluginResourceLoadFactory; import org.pf4j.Plugin; -import org.pf4j.PluginException; import org.pf4j.PluginWrapper; /** @@ -21,45 +20,47 @@ public abstract class BasePlugin extends Plugin { @Override - public final void start() throws PluginException { - pluginResourceLoadFactory.load(this); + public final void start() { + try { + startEvent(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + pluginResourceLoadFactory.load(this); + } } @Override - public final void delete() throws PluginException { - deleteEvent(); + public final void delete() { + try { + deleteEvent(); + } catch (Exception e){ + e.printStackTrace(); + } finally { + pluginResourceLoadFactory.unload(this); + } + } @Override public final void stop() { - stopEvent(); + try { + stopEvent(); + } catch (Exception e){ + e.printStackTrace(); + } finally { + pluginResourceLoadFactory.unload(this); + } } - - /** - * 启动事件 - * @throws PluginException PluginException - */ - protected abstract void startEvent() throws PluginException; - - /** - * 删除事件 - * @throws PluginException PluginException - */ - protected abstract void deleteEvent() throws PluginException; - - /** - * 停止事件 - */ - protected abstract void stopEvent(); - /** * 扫描包。默认为当前类包名。可重写自定义包名 * @return 包名 */ public String scanPackage(){ - return this.getCurrentPackageName(); + // 获取当前实现类的包名 + return this.getClass().getPackage().getName(); } @@ -71,12 +72,20 @@ public abstract class BasePlugin extends Plugin { return pluginResourceLoadFactory; } + /** - * 获取当前实现类的包名 - * @return 包名 + * 启动事件. Spring 容器都没有准备。无法使用注入。 */ - private String getCurrentPackageName(){ - return this.getClass().getPackage().getName(); - } + protected abstract void startEvent(); + + /** + * 删除事件. 在插件删除时触发。 + */ + protected abstract void deleteEvent(); + + /** + * 停止事件. 在插件停止时触发。 + */ + protected abstract void stopEvent(); } -- Gitee From b0f6b00c0cd036a1ba60c9140e60f24a2a1ae96e Mon Sep 17 00:00:00 2001 From: StarBlues Date: Mon, 28 Oct 2019 16:43:18 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E7=AE=80=E5=8C=96=E9=9B=86=E6=88=90?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E7=9A=84=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/config/ExamplePluginListener.java | 3 +- .../example/main/config/PluginBeanConfig.java | 39 +---- .../main/plugin/ConsoleNameFactory.java | 2 +- .../example/main/rest/HelloResource.java | 2 +- .../example/main/rest/PluginResource.java | 2 +- .../integration-mybatis-main/pom.xml | 2 +- .../mybatis/main/config/PluginBeanConfig.java | 81 ++++++---- .../main/config/PluginConfiguration.java | 128 ---------------- .../com/mybatis/main/rest/PluginResource.java | 3 +- .../src/main/resources/application-dev.yml | 2 +- .../src/main/resources/application-prod.yml | 2 +- .../main/config/PluginBeanConfig.java | 39 +---- .../src/main/resources/application-dev.yml | 2 +- .../src/main/resources/application-prod.yml | 2 +- .../integration/ConfigurationBuilder.java | 145 ++++++++++++++++++ .../integration/DefaultPluginApplication.java | 134 ---------------- .../AbstractPluginApplication.java | 69 +++++++++ .../application/AutoPluginApplication.java | 62 ++++++++ .../application/DefaultPluginApplication.java | 96 ++++++++++++ .../{ => application}/PluginApplication.java | 21 ++- .../integration/application/package-info.java | 7 + .../initialize/AbstractPluginInitializer.java | 48 ------ .../initialize/AutoPluginInitializer.java | 38 ----- .../initialize/ManualPluginInitializer.java | 32 ---- .../initialize/PluginInitializer.java | 19 --- .../listener/PluginListenerFactory.java | 9 +- .../operator/DefaultPluginOperator.java | 4 +- .../DefaultPf4JFactory.java} | 13 +- .../Pf4jFactory.java} | 10 +- .../AbstractPluginSpringBeanRefresh.java | 2 +- .../refresh/AbstractSpringBeanRefresh.java | 2 +- .../integration/user/DefaultPluginUser.java | 4 +- .../starblues/utils/GlobalRegistryInfo.java | 5 +- 33 files changed, 507 insertions(+), 522 deletions(-) delete mode 100644 example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginConfiguration.java create mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java delete mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultPluginApplication.java create mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java create mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java create mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java rename springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/{ => application}/PluginApplication.java (41%) create mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/package-info.java delete mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AbstractPluginInitializer.java delete mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AutoPluginInitializer.java delete mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/ManualPluginInitializer.java delete mode 100644 springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/PluginInitializer.java rename springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/{DefaultIntegrationFactory.java => pf4j/DefaultPf4JFactory.java} (84%) rename springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/{IntegrationFactory.java => pf4j/Pf4jFactory.java} (43%) diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/ExamplePluginListener.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/ExamplePluginListener.java index 838cbdd..9ee0a9a 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/ExamplePluginListener.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/ExamplePluginListener.java @@ -1,11 +1,10 @@ package com.basic.example.main.config; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import com.gitee.starblues.integration.listener.PluginListener; import com.gitee.starblues.integration.user.PluginUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; /** diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java index 72e4f9e..f3f238f 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/config/PluginBeanConfig.java @@ -1,9 +1,7 @@ package com.basic.example.main.config; -import com.gitee.starblues.integration.*; -import com.gitee.starblues.integration.initialize.AutoPluginInitializer; -import com.gitee.starblues.integration.initialize.PluginInitializer; -import org.pf4j.PluginManager; +import com.gitee.starblues.integration.application.PluginApplication; +import com.gitee.starblues.integration.application.AutoPluginApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -16,39 +14,14 @@ import org.springframework.context.annotation.Configuration; @Configuration public class PluginBeanConfig { - /** - * 通过默认的集成工厂返回 PluginManager - * @param integrationConfiguration 集成的配置文件 - * @return - */ - @Bean - public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) { - IntegrationFactory integrationFactory = new DefaultIntegrationFactory(); - return integrationFactory.getPluginManager(integrationConfiguration); - } /** - * 定义默认的插件应用。使用可以注入它操作插件。 - * @return + * 定义插件应用。使用可以注入它操作插件。 + * @return PluginApplication */ @Bean public PluginApplication pluginApplication(){ - DefaultPluginApplication defaultPluginApplication = new DefaultPluginApplication(); - defaultPluginApplication.addListener(ExamplePluginListener.class); - return defaultPluginApplication; - } - - /** - * 初始化插件。此处定义可以在系统启动时自动加载插件。 - * 如果想手动加载插件, 则可以使用 com.plugin.development.integration.initialize.ManualPluginInitializer 来初始化插件。 - * @param pluginApplication - * @return - */ - @Bean - public PluginInitializer pluginInitializer(PluginApplication pluginApplication, - PluginListener pluginListener){ - AutoPluginInitializer autoPluginInitializer = new AutoPluginInitializer(pluginApplication); - autoPluginInitializer.setPluginInitializerListener(pluginListener); - return autoPluginInitializer; + // 实例化自动初始化插件的PluginApplication + return new AutoPluginApplication(); } } diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/ConsoleNameFactory.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/ConsoleNameFactory.java index 889b35f..8315a9e 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/ConsoleNameFactory.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/plugin/ConsoleNameFactory.java @@ -1,6 +1,6 @@ package com.basic.example.main.plugin; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import com.gitee.starblues.integration.refresh.AbstractPluginSpringBeanRefresh; import org.springframework.stereotype.Component; diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java index 8d35858..37fd5e1 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/HelloResource.java @@ -1,7 +1,7 @@ package com.basic.example.main.rest; import com.basic.example.main.plugin.Hello; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import com.gitee.starblues.integration.user.PluginUser; import com.basic.example.main.plugin.ConsoleName; import com.basic.example.main.plugin.ConsoleNameFactory; diff --git a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java index 2b6c367..61a1220 100644 --- a/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java +++ b/example/basic-example/basic-example-main/src/main/java/com/basic/example/main/rest/PluginResource.java @@ -1,6 +1,6 @@ package com.basic.example.main.rest; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import com.gitee.starblues.integration.operator.PluginOperator; import com.gitee.starblues.integration.operator.module.PluginInfo; import org.springframework.beans.factory.annotation.Autowired; diff --git a/example/integration-mybatis/integration-mybatis-main/pom.xml b/example/integration-mybatis/integration-mybatis-main/pom.xml index 695dae3..018e104 100644 --- a/example/integration-mybatis/integration-mybatis-main/pom.xml +++ b/example/integration-mybatis/integration-mybatis-main/pom.xml @@ -8,7 +8,7 @@ org.springframework.boot spring-boot-starter-parent - 2.0.3.RELEASE + 2.1.1.RELEASE diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java index 4fd7c90..853f2ec 100644 --- a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java +++ b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginBeanConfig.java @@ -2,11 +2,13 @@ package com.mybatis.main.config; import com.gitee.starblues.extension.mybatis.SpringBootMybatisExtension; import com.gitee.starblues.integration.*; -import com.gitee.starblues.integration.initialize.AutoPluginInitializer; -import com.gitee.starblues.integration.initialize.PluginInitializer; -import org.pf4j.PluginManager; +import com.gitee.starblues.integration.application.AutoPluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; +import org.pf4j.RuntimeMode; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; /** * @Description: 插件集成配置 @@ -16,42 +18,67 @@ import org.springframework.context.annotation.Configuration; * @Update Date Time: * @see */ -@Configuration +@Component +@ConfigurationProperties(prefix = "plugin") public class PluginBeanConfig { /** - * 通过默认的集成工厂返回 PluginManager - * @param integrationConfiguration 集成的配置文件 - * @return PluginManager - * @throws Exception + * 运行模式 + * 开发环境: development、dev + * 生产/部署 环境: deployment、prod */ - @Bean - public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) { - IntegrationFactory integrationFactory = new DefaultIntegrationFactory(); - return integrationFactory.getPluginManager(integrationConfiguration); - } + @Value("${runMode:dev}") + private String runMode; + + /** + * 插件的路径 + */ + @Value("${pluginPath:plugins}") + private String pluginPath; /** - * 定义默认的插件应用。使用可以注入它操作插件。 - * @return + * 插件文件的路径 */ + @Value("${pluginConfigFilePath:pluginConfigs}") + private String pluginConfigFilePath; + + + @Bean - public PluginApplication pluginApplication(){ - DefaultPluginApplication defaultPluginApplication = new DefaultPluginApplication(); - defaultPluginApplication.addExtension(new SpringBootMybatisExtension()); - return defaultPluginApplication; + public IntegrationConfiguration configuration(){ + return ConfigurationBuilder.toBuilder() + .runtimeMode(RuntimeMode.byName(runMode)) + .pluginPath(pluginPath) + .pluginConfigFilePath(pluginConfigFilePath) + .uploadTempPath("temp") + .backupPath("backupPlugin") + .pluginRestControllerPathPrefix("/api/plugin") + .enablePluginIdRestControllerPathPrefix(true) + .build(); } + /** - * 初始化插件。此处定义可以在系统启动时自动加载插件。 - * 如果想手动加载插件, 则可以使用 com.plugin.development.integration.initialize.ManualPluginInitializer 来初始化插件。 - * @param pluginApplication - * @return + * 定义插件应用。使用可以注入它操作插件。 + * @return PluginApplication */ @Bean - public PluginInitializer pluginInitializer(PluginApplication pluginApplication){ - AutoPluginInitializer autoPluginInitializer = new AutoPluginInitializer(pluginApplication); - return autoPluginInitializer; + public PluginApplication pluginApplication(){ + // 实例化自动初始化插件的PluginApplication + PluginApplication pluginApplication = new AutoPluginApplication(); + pluginApplication.addExtension(new SpringBootMybatisExtension()); + return pluginApplication; + } + + public void setRunMode(String runMode) { + this.runMode = runMode; + } + + public void setPluginPath(String pluginPath) { + this.pluginPath = pluginPath; } + public void setPluginConfigFilePath(String pluginConfigFilePath) { + this.pluginConfigFilePath = pluginConfigFilePath; + } } diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginConfiguration.java b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginConfiguration.java deleted file mode 100644 index b6442d3..0000000 --- a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/config/PluginConfiguration.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.mybatis.main.config; - -import com.gitee.starblues.integration.DefaultIntegrationConfiguration; -import org.pf4j.RuntimeMode; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - - -/** - * @Description: - * @Author: zhangzhuo - * @Version: 1.0 - * @Create Date Time: 2019-05-25 12:36 - * @Update Date Time: - * @see - */ -@Component -@ConfigurationProperties(prefix = "plugin") -public class PluginConfiguration extends DefaultIntegrationConfiguration { - - /** - * 运行模式 - * 开发环境: development、dev - * 生产/部署 环境: deployment、prod - */ - @Value("${runMode:dev}") - private String runMode; - - /** - * 插件的路径 - */ - @Value("${pluginPath:plugins}") - private String pluginPath; - - /** - * 插件文件的路径 - */ - @Value("${pluginConfigFilePath:pluginConfigs}") - private String pluginConfigFilePath; - - - @Override - public RuntimeMode environment() { - return RuntimeMode.byName(runMode); - } - - @Override - public String pluginPath() { - return pluginPath; - } - - @Override - public String pluginConfigFilePath() { - return pluginConfigFilePath; - } - - /** - * 重写上传插件包的临时存储路径。只适用于生产环境 - * @return String - */ - @Override - public String uploadTempPath() { - return "temp"; - } - - /** - * 重写插件备份路径。只适用于生产环境 - * @return String - */ - @Override - public String backupPath() { - return "backupPlugin"; - } - - /** - * 重写插件RestController请求的路径前缀 - * @return String - */ - @Override - public String pluginRestControllerPathPrefix() { - return "/api/plugin"; - } - - /** - * 重写是否启用插件id作为RestController请求的路径前缀。 - * 启动则插件id会作为二级路径前缀。即: /api/plugin/pluginId/** - * @return String - */ - @Override - public boolean enablePluginIdRestControllerPathPrefix() { - return true; - } - - public String getRunMode() { - return runMode; - } - - public void setRunMode(String runMode) { - this.runMode = runMode; - } - - - public String getPluginPath() { - return pluginPath; - } - - public void setPluginPath(String pluginPath) { - this.pluginPath = pluginPath; - } - - public String getPluginConfigFilePath() { - return pluginConfigFilePath; - } - - public void setPluginConfigFilePath(String pluginConfigFilePath) { - this.pluginConfigFilePath = pluginConfigFilePath; - } - - @Override - public String toString() { - return "PluginArgConfiguration{" + - "runMode='" + runMode + '\'' + - ", pluginPath='" + pluginPath + '\'' + - ", pluginConfigFilePath='" + pluginConfigFilePath + '\'' + - '}'; - } -} diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java index 6f67fea..7b4e3f6 100644 --- a/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java +++ b/example/integration-mybatis/integration-mybatis-main/src/main/java/com/mybatis/main/rest/PluginResource.java @@ -1,10 +1,9 @@ package com.mybatis.main.rest; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import com.gitee.starblues.integration.operator.PluginOperator; import com.gitee.starblues.integration.operator.module.PluginInfo; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-dev.yml b/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-dev.yml index c4d7505..df5d62b 100644 --- a/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-dev.yml +++ b/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-dev.yml @@ -3,7 +3,7 @@ server: spring: datasource: - url: jdbc:mysql://127.0.0.1:3306/plugin?useUnicode=true&useSSL=false&characterEncoding=utf8 + url: jdbc:mysql://127.0.0.1:3306/plugin?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver diff --git a/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-prod.yml b/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-prod.yml index eafc8bb..45b1f6e 100644 --- a/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-prod.yml +++ b/example/integration-mybatis/integration-mybatis-main/src/main/resources/application-prod.yml @@ -3,7 +3,7 @@ server: spring: datasource: - url: jdbc:mysql://127.0.0.1:3306/plugin?useUnicode=true&useSSL=false&characterEncoding=utf8 + url: jdbc:mysql://127.0.0.1:3306/plugin?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver diff --git a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java index 3d74552..93c14a0 100644 --- a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java +++ b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/java/com/mybatisplus/main/config/PluginBeanConfig.java @@ -1,10 +1,8 @@ package com.mybatisplus.main.config; import com.gitee.starblues.extension.mybatis.SpringBootMybatisExtension; -import com.gitee.starblues.integration.*; -import com.gitee.starblues.integration.initialize.AutoPluginInitializer; -import com.gitee.starblues.integration.initialize.PluginInitializer; -import org.pf4j.PluginManager; +import com.gitee.starblues.integration.application.PluginApplication; +import com.gitee.starblues.integration.application.AutoPluginApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -19,38 +17,17 @@ import org.springframework.context.annotation.Configuration; @Configuration public class PluginBeanConfig { - /** - * 通过默认的集成工厂返回 PluginManager - * @param integrationConfiguration 集成的配置文件 - * @return - */ - @Bean - public PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) { - IntegrationFactory integrationFactory = new DefaultIntegrationFactory(); - return integrationFactory.getPluginManager(integrationConfiguration); - } /** - * 定义默认的插件应用。使用可以注入它操作插件。 - * @return + * 定义插件应用。使用可以注入它操作插件。 + * @return PluginApplication */ @Bean public PluginApplication pluginApplication(){ - DefaultPluginApplication defaultPluginApplication = new DefaultPluginApplication(); - defaultPluginApplication.addExtension(new SpringBootMybatisExtension()); - return defaultPluginApplication; - } - - /** - * 初始化插件。此处定义可以在系统启动时自动加载插件。 - * 如果想手动加载插件, 则可以使用 com.plugin.development.integration.initialize.ManualPluginInitializer 来初始化插件。 - * @param pluginApplication - * @return - */ - @Bean - public PluginInitializer pluginInitializer(PluginApplication pluginApplication){ - AutoPluginInitializer autoPluginInitializer = new AutoPluginInitializer(pluginApplication); - return autoPluginInitializer; + // 实例化自动初始化插件的PluginApplication + PluginApplication pluginApplication = new AutoPluginApplication(); + pluginApplication.addExtension(new SpringBootMybatisExtension()); + return pluginApplication; } } diff --git a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-dev.yml b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-dev.yml index fb86076..25c6248 100644 --- a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-dev.yml +++ b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-dev.yml @@ -3,7 +3,7 @@ server: spring: datasource: - url: jdbc:mysql://127.0.0.1:3306/plugin_mybatis_plus?useUnicode=true&useSSL=false&characterEncoding=utf8 + url: jdbc:mysql://127.0.0.1:3306/plugin_mybatis_plus?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver diff --git a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-prod.yml b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-prod.yml index fb9583f..421c48b 100644 --- a/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-prod.yml +++ b/example/integration-mybatisplus/integration-mybatisplus-main/src/main/resources/application-prod.yml @@ -3,7 +3,7 @@ server: spring: datasource: - url: jdbc:mysql://127.0.0.1:3306/plugin_mybatis_plus?useUnicode=true&useSSL=false&characterEncoding=utf8 + url: jdbc:mysql://127.0.0.1:3306/plugin_mybatis_plus?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java new file mode 100644 index 0000000..32a6d26 --- /dev/null +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java @@ -0,0 +1,145 @@ +package com.gitee.starblues.integration; + +import org.pf4j.RuntimeMode; +import org.springframework.util.StringUtils; + +import java.util.Objects; + +/** + * 通过构造者进行配置插件初始化配置 + * + * @author zhangzhuo + * @version 1.0 + */ +public class ConfigurationBuilder extends DefaultIntegrationConfiguration{ + + private RuntimeMode runtimeMode = RuntimeMode.DEVELOPMENT; + private String pluginPath = ""; + private String pluginConfigFilePath = ""; + + private String uploadTempPath; + private String backupPath; + private String pluginRestControllerPathPrefix; + private Boolean enablePluginIdRestControllerPathPrefix; + + + public ConfigurationBuilder(Builder builder) { + this.runtimeMode = Objects.requireNonNull(builder.runtimeMode, "runtimeMode can't be empty"); + this.pluginPath = Objects.requireNonNull(builder.pluginPath, "pluginPath can't be empty"); + this.pluginConfigFilePath = Objects.requireNonNull(builder.pluginConfigFilePath, + "pluginConfigFilePath can't be empty"); + this.uploadTempPath = builder.uploadTempPath; + this.backupPath = builder.backupPath; + this.pluginRestControllerPathPrefix = builder.pluginRestControllerPathPrefix; + this.enablePluginIdRestControllerPathPrefix = builder.enablePluginIdRestControllerPathPrefix; + } + + public static Builder toBuilder(){ + return new Builder(); + } + + public static class Builder{ + private RuntimeMode runtimeMode = RuntimeMode.DEVELOPMENT; + private String pluginPath = ""; + private String pluginConfigFilePath = ""; + + private String uploadTempPath; + private String backupPath; + private String pluginRestControllerPathPrefix; + private Boolean enablePluginIdRestControllerPathPrefix; + + public Builder runtimeMode(RuntimeMode runtimeMode){ + this.runtimeMode = runtimeMode; + return this; + } + + public Builder pluginPath(String pluginPath){ + this.pluginPath = pluginPath; + return this; + } + + public Builder pluginConfigFilePath(String pluginConfigFilePath){ + this.pluginConfigFilePath = pluginConfigFilePath; + return this; + } + + public Builder uploadTempPath(String uploadTempPath){ + this.uploadTempPath = uploadTempPath; + return this; + } + + public Builder backupPath(String backupPath){ + this.backupPath = backupPath; + return this; + } + + public Builder pluginRestControllerPathPrefix(String pluginRestControllerPathPrefix){ + this.pluginRestControllerPathPrefix = pluginRestControllerPathPrefix; + return this; + } + + public Builder enablePluginIdRestControllerPathPrefix(Boolean enablePluginIdRestControllerPathPrefix){ + this.enablePluginIdRestControllerPathPrefix = enablePluginIdRestControllerPathPrefix; + return this; + } + + public ConfigurationBuilder build(){ + return new ConfigurationBuilder(this); + } + + } + + + + @Override + public RuntimeMode environment() { + return runtimeMode; + } + + @Override + public String pluginPath() { + return pluginPath; + } + + @Override + public String pluginConfigFilePath() { + return pluginConfigFilePath; + } + + + @Override + public String uploadTempPath() { + if(StringUtils.isEmpty(uploadTempPath)){ + return super.uploadTempPath(); + } else { + return uploadTempPath; + } + } + + @Override + public String backupPath() { + if(StringUtils.isEmpty(backupPath)){ + return super.backupPath(); + } else { + return backupPath; + } + } + + @Override + public String pluginRestControllerPathPrefix() { + if(StringUtils.isEmpty(pluginRestControllerPathPrefix)){ + return super.pluginRestControllerPathPrefix(); + } else { + return pluginRestControllerPathPrefix; + } + } + + @Override + public boolean enablePluginIdRestControllerPathPrefix() { + if(enablePluginIdRestControllerPathPrefix == null){ + return super.enablePluginIdRestControllerPathPrefix(); + } else { + return enablePluginIdRestControllerPathPrefix; + } + } +} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultPluginApplication.java deleted file mode 100644 index ea307bc..0000000 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultPluginApplication.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.gitee.starblues.integration; - -import com.gitee.starblues.extension.AbstractExtension; -import com.gitee.starblues.extension.ExtensionFactory; -import com.gitee.starblues.integration.listener.PluginListener; -import com.gitee.starblues.integration.listener.PluginListenerFactory; -import com.gitee.starblues.integration.operator.DefaultPluginOperator; -import com.gitee.starblues.integration.operator.PluginOperator; -import com.gitee.starblues.integration.user.DefaultPluginUser; -import com.gitee.starblues.integration.user.PluginUser; -import org.pf4j.PluginManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.support.GenericApplicationContext; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * 开发者直接使用的。插件应用 - * @author zhangzhuo - * @version 2.0.2 - */ -public class DefaultPluginApplication implements ApplicationContextAware, PluginApplication { - - private final Logger log = LoggerFactory.getLogger(DefaultPluginApplication.class); - - private ApplicationContext applicationContext; - private PluginManager pluginManager; - private ExtensionFactory extensionFactory = ExtensionFactory.getSingleton(); - - private PluginOperator pluginOperator; - private PluginUser pluginUser; - - private PluginListenerFactory listenerFactory = new PluginListenerFactory(); - - public DefaultPluginApplication() { - this(null); - } - - - public DefaultPluginApplication(List pluginListeners) { - addListener(pluginListeners); - } - - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - Objects.requireNonNull(applicationContext); - this.applicationContext = applicationContext; - this.pluginManager = applicationContext.getBean(PluginManager.class); - try { - IntegrationConfiguration configuration = applicationContext.getBean(IntegrationConfiguration.class); - this.pluginUser = new DefaultPluginUser(this.applicationContext, this.pluginManager); - this.pluginOperator = new DefaultPluginOperator( - applicationContext, - configuration, - this.pluginManager, - this.listenerFactory - ); - } catch (Exception e) { - throw new BeanCreationException("Instant PluginUser or PluginOperator Failure : " + e.getMessage(), e); - } - } - - - @Override - public PluginOperator getPluginOperator() { - assertInjected(); - return this.pluginOperator; - } - - @Override - public PluginUser getPluginUser() { - assertInjected(); - return this.pluginUser; - } - - /** - * 检查注入 - */ - private void assertInjected() { - if (this.applicationContext == null) { - throw new RuntimeException("ApplicationContext is null, Please check whether the DefaultPluginApplication is injected"); - } - if (this.pluginManager == null) { - throw new RuntimeException("PluginManager is null, Please check whether the PluginManager is injected"); - } - if (this.pluginOperator == null) { - throw new RuntimeException("PluginOperator is null," + - " Please check whether the PluginManager or ApplicationContext is injected"); - } - if (this.pluginUser == null) { - throw new RuntimeException("pluginUser is null," + - " Please check whether the PluginManager or ApplicationContext is injected"); - } - } - - /** - * 添加插件扩展 - * @param extension 扩展实现对象 - * @return DefaultPluginApplication - */ - public DefaultPluginApplication addExtension(AbstractExtension extension) { - this.extensionFactory.addExtension(extension); - return this; - } - - - @Override - public void addListener(PluginListener pluginListener) { - this.listenerFactory.addPluginListener(pluginListener); - } - - @Override - public void addListener(Class pluginListenerClass) { - listenerFactory.addPluginListener(pluginListenerClass); - } - - @Override - public void addListener(List pluginListeners) { - if(pluginListeners == null || pluginListeners.isEmpty()){ - return; - } - for (PluginListener pluginListener : pluginListeners) { - this.listenerFactory.addPluginListener(pluginListener); - } - } -} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java new file mode 100644 index 0000000..7b749e0 --- /dev/null +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java @@ -0,0 +1,69 @@ +package com.gitee.starblues.integration.application; + +import com.gitee.starblues.extension.AbstractExtension; +import com.gitee.starblues.extension.ExtensionFactory; +import com.gitee.starblues.integration.IntegrationConfiguration; +import com.gitee.starblues.integration.listener.PluginListener; +import com.gitee.starblues.integration.listener.PluginListenerFactory; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.ApplicationContext; + +import java.util.List; + +/** + * 公用的的插件应用 + * + * @author zhangzhuo + * @version 1.0 + */ +public abstract class AbstractPluginApplication implements PluginApplication { + + protected final PluginListenerFactory listenerFactory = new PluginListenerFactory(); + protected final ExtensionFactory extensionFactory = ExtensionFactory.getSingleton(); + + + @Override + public void addExtension(AbstractExtension extension) { + extensionFactory.addExtension(extension); + } + + @Override + public void addListener(PluginListener pluginListener) { + this.listenerFactory.addPluginListener(pluginListener); + } + + @Override + public void addListener(Class pluginListenerClass) { + listenerFactory.addPluginListener(pluginListenerClass); + } + + @Override + public void addListener(List pluginListeners) { + if(pluginListeners == null || pluginListeners.isEmpty()){ + return; + } + for (PluginListener pluginListener : pluginListeners) { + this.listenerFactory.addPluginListener(pluginListener); + } + } + + /** + * 子类可通过Application 获取插件定义的配置 + * @param applicationContext applicationContext + * @return IntegrationConfiguration + */ + protected IntegrationConfiguration getConfiguration(ApplicationContext applicationContext){ + IntegrationConfiguration configuration = null; + try { + configuration = applicationContext.getBean(IntegrationConfiguration.class); + } catch (Exception e){ + // no show exception + } + if(configuration == null){ + throw new BeanCreationException("Not Found IntegrationConfiguration, Please define " + + "IntegrationConfiguration to Spring Bean."); + } + return configuration; + } + +} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java new file mode 100644 index 0000000..0637be9 --- /dev/null +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java @@ -0,0 +1,62 @@ +package com.gitee.starblues.integration.application; + +import com.gitee.starblues.integration.pf4j.Pf4jFactory; +import com.gitee.starblues.integration.listener.PluginInitializerListener; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * 自动初始化的 PluginApplication。该PluginApplication 基于 Spring InitializingBean 自动初始化插件。 + * + * @author zhangzhuo + * @version 1.0 + */ +public class AutoPluginApplication extends DefaultPluginApplication + implements PluginApplication, InitializingBean, ApplicationContextAware { + + private ApplicationContext applicationContext; + private PluginInitializerListener pluginInitializerListener; + + public AutoPluginApplication() { + super(); + } + + public AutoPluginApplication(Pf4jFactory integrationFactory) { + super(integrationFactory); + } + + /** + * 设置插件初始化监听器 + * @param pluginInitializerListener 插件监听器 + */ + public void setPluginInitializerListener(PluginInitializerListener pluginInitializerListener) { + this.pluginInitializerListener = pluginInitializerListener; + } + + + @Override + public void initialize(ApplicationContext applicationContext, + PluginInitializerListener listener) { + // 此处不允许手动初始化! + throw new RuntimeException("Cannot be initialized manually"); + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + /** + * Spring boot bean属性被Set完后调用。会自动初始化插件 + * @throws Exception 初始化异常 + */ + @Override + public void afterPropertiesSet() throws Exception { + if(applicationContext == null){ + throw new Exception("Auto initialize failed. ApplicationContext Not injected."); + } + super.initialize(applicationContext, pluginInitializerListener); + } +} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java new file mode 100644 index 0000000..6da67e5 --- /dev/null +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java @@ -0,0 +1,96 @@ +package com.gitee.starblues.integration.application; + +import com.gitee.starblues.integration.pf4j.DefaultPf4JFactory; +import com.gitee.starblues.integration.IntegrationConfiguration; +import com.gitee.starblues.integration.pf4j.Pf4jFactory; +import com.gitee.starblues.integration.listener.PluginInitializerListener; +import com.gitee.starblues.integration.operator.DefaultPluginOperator; +import com.gitee.starblues.integration.operator.PluginOperator; +import com.gitee.starblues.integration.user.DefaultPluginUser; +import com.gitee.starblues.integration.user.PluginUser; +import org.pf4j.PluginManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; + + +/** + * 默认的插件 PluginApplication + * @author zhangzhuo + * @version 2.0.2 + */ +public class DefaultPluginApplication extends AbstractPluginApplication { + + private final Logger log = LoggerFactory.getLogger(DefaultPluginApplication.class); + + private Pf4jFactory integrationFactory; + private PluginUser pluginUser; + private PluginOperator pluginOperator; + + private AtomicBoolean beInitialized = new AtomicBoolean(false); + + public DefaultPluginApplication() { + } + + public DefaultPluginApplication(Pf4jFactory integrationFactory){ + this.integrationFactory = integrationFactory; + } + + + @Override + public synchronized void initialize(ApplicationContext applicationContext, + PluginInitializerListener listener) { + Objects.requireNonNull(applicationContext, "ApplicationContext can't be null"); + if(beInitialized.get()){ + throw new RuntimeException("Plugin has been initialized"); + } + IntegrationConfiguration configuration = getConfiguration(applicationContext); + if(integrationFactory == null){ + integrationFactory = new DefaultPf4JFactory(configuration); + } + PluginManager pluginManager = integrationFactory.getPluginManager(); + pluginUser = new DefaultPluginUser(applicationContext, pluginManager); + pluginOperator = new DefaultPluginOperator( + applicationContext, + configuration, + pluginManager, + this.listenerFactory + ); + try { + pluginOperator.initPlugins(listener); + beInitialized.set(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @Override + public PluginOperator getPluginOperator() { + assertInjected(); + return pluginOperator; + } + + @Override + public PluginUser getPluginUser() { + assertInjected(); + return pluginUser; + } + + /** + * 检查注入 + */ + private void assertInjected() { + if (this.pluginUser == null) { + throw new RuntimeException("PluginUser is null, Please check whether the DefaultPluginApplication is injected"); + } + if (this.pluginOperator == null) { + throw new RuntimeException("PluginOperator is null, Please check whether the DefaultPluginApplication is injected"); + } + } + + +} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java similarity index 41% rename from springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginApplication.java rename to springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java index d071f67..b61ea77 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginApplication.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java @@ -1,15 +1,26 @@ -package com.gitee.starblues.integration; +package com.gitee.starblues.integration.application; +import com.gitee.starblues.extension.AbstractExtension; +import com.gitee.starblues.integration.PluginListenerContext; +import com.gitee.starblues.integration.listener.PluginInitializerListener; import com.gitee.starblues.integration.operator.PluginOperator; import com.gitee.starblues.integration.user.PluginUser; +import org.springframework.context.ApplicationContext; /** - * 插件应用。需要主程序定义成@Bean + * 插件应用。 * @author zhangzhuo * @version 2.0.2 */ public interface PluginApplication extends PluginListenerContext { + /** + * 初始化 + * @param applicationContext Spring上下文 + * @param listener 插件初始化监听者 + */ + void initialize(ApplicationContext applicationContext, PluginInitializerListener listener); + /** * 获得插插件操作者 @@ -23,4 +34,10 @@ public interface PluginApplication extends PluginListenerContext { */ PluginUser getPluginUser(); + /** + * 添加扩展 + * @param extension 扩展类 + */ + void addExtension(AbstractExtension extension); + } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/package-info.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/package-info.java new file mode 100644 index 0000000..96722a4 --- /dev/null +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/package-info.java @@ -0,0 +1,7 @@ +/** + * 插件 PluginApplication 的实现包 + * + * @author zhangzhuo + * @version 1.0 + */ +package com.gitee.starblues.integration.application; \ No newline at end of file diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AbstractPluginInitializer.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AbstractPluginInitializer.java deleted file mode 100644 index a9e8726..0000000 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AbstractPluginInitializer.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.gitee.starblues.integration.initialize; - -import com.gitee.starblues.integration.listener.PluginInitializerListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 抽象的插件初始化者 - * @author zhangzhuo - * @version 1.0 - * @see AutoPluginInitializer - * @see ManualPluginInitializer - */ -public abstract class AbstractPluginInitializer implements PluginInitializer{ - - private final Logger log = LoggerFactory.getLogger(this.getClass()); - - protected PluginInitializerListener pluginInitializerListener; - - protected AbstractPluginInitializer() { - } - - protected AbstractPluginInitializer(PluginInitializerListener pluginInitializerListener) { - this.pluginInitializerListener = pluginInitializerListener; - } - - @Override - public void initialize() throws Exception { - log.info("Start execute plugin initializer."); - this.executeInitialize(); - } - - /** - * 执行初始化 - * @throws Exception 插件执行初始化异常 - */ - public abstract void executeInitialize() throws Exception; - - - /** - * 设置监听者 - * @param pluginInitializerListener 初始化监听者 - */ - public void setPluginInitializerListener(PluginInitializerListener pluginInitializerListener) { - this.pluginInitializerListener = pluginInitializerListener; - } - -} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AutoPluginInitializer.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AutoPluginInitializer.java deleted file mode 100644 index 28ef0c8..0000000 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/AutoPluginInitializer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gitee.starblues.integration.initialize; - -import com.gitee.starblues.integration.PluginApplication; -import com.gitee.starblues.integration.listener.PluginInitializerListener; -import com.gitee.starblues.integration.operator.PluginOperator; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.annotation.PostConstruct; - -/** - * 自动初始化者 - * @author zhangzhuo - * @version 1.0 - */ -public class AutoPluginInitializer extends AbstractPluginInitializer { - - - private final PluginOperator pluginOperator; - - - public AutoPluginInitializer(@Autowired PluginApplication pluginApplication) { - this.pluginOperator = pluginApplication.getPluginOperator(); - } - - public AutoPluginInitializer(PluginApplication pluginApplication, - PluginInitializerListener pluginInitializerListener) { - super(pluginInitializerListener); - this.pluginOperator = pluginApplication.getPluginOperator(); - } - - - @PostConstruct - @Override - public void executeInitialize() throws Exception { - pluginOperator.initPlugins(pluginInitializerListener); - } - -} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/ManualPluginInitializer.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/ManualPluginInitializer.java deleted file mode 100644 index ae1d9dc..0000000 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/ManualPluginInitializer.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gitee.starblues.integration.initialize; - -import com.gitee.starblues.integration.PluginApplication; -import com.gitee.starblues.integration.listener.PluginInitializerListener; -import com.gitee.starblues.integration.operator.PluginOperator; - -/** - * 插件手动初始化者 - * @author zhangzhuo - * @version 1.0 - */ -public class ManualPluginInitializer extends AbstractPluginInitializer { - - private final PluginOperator pluginOperator; - - public ManualPluginInitializer(PluginApplication pluginApplication) { - this.pluginOperator = pluginApplication.getPluginOperator(); - } - - public ManualPluginInitializer(PluginApplication pluginApplication, - PluginInitializerListener pluginInitializerListener) { - super(pluginInitializerListener); - this.pluginOperator = pluginApplication.getPluginOperator(); - } - - - @Override - public void executeInitialize() throws Exception { - pluginOperator.initPlugins(pluginInitializerListener); - } - -} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/PluginInitializer.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/PluginInitializer.java deleted file mode 100644 index 4c4b094..0000000 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/initialize/PluginInitializer.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.gitee.starblues.integration.initialize; - - -/** - * 插件初始化者 - * @author zhangzhuo - * @version 1.0 - * @see AbstractPluginInitializer - */ -public interface PluginInitializer { - - /** - * 初始化 - * @throws Exception 插件安装异常 - */ - void initialize() throws Exception; - - -} diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java index 83cd744..6c3e9d0 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java @@ -1,6 +1,5 @@ package com.gitee.starblues.integration.listener; -import org.springframework.context.ApplicationContext; import org.springframework.context.support.GenericApplicationContext; import java.util.ArrayList; @@ -93,4 +92,12 @@ public class PluginListenerFactory implements PluginListener{ public List getListeners() { return listeners; } + + /** + * 得到监听者class + * @return 监听者class集合 + */ + public List getListenerClasses() { + return listenerClasses; + } } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index 0b157cd..8c4b3e4 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -57,8 +57,8 @@ public class DefaultPluginOperator implements PluginOperator { IntegrationConfiguration integrationConfiguration, PluginManager pluginManager, PluginListenerFactory pluginListenerFactory) { - Objects.requireNonNull(integrationConfiguration); - Objects.requireNonNull(pluginManager); + Objects.requireNonNull(integrationConfiguration, "IntegrationConfiguration can't be null"); + Objects.requireNonNull(pluginManager, "PluginManager can't be null"); this.integrationConfiguration = integrationConfiguration; this.pluginManager = pluginManager; this.pluginFactory = new DefaultPluginFactory(applicationContext, pluginListenerFactory); diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java similarity index 84% rename from springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java rename to springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java index 50cc15a..f6fe977 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/DefaultIntegrationFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java @@ -1,5 +1,6 @@ -package com.gitee.starblues.integration; +package com.gitee.starblues.integration.pf4j; +import com.gitee.starblues.integration.IntegrationConfiguration; import org.pf4j.*; import java.nio.file.Path; @@ -11,11 +12,17 @@ import java.util.Objects; * @author zhangzhuo * @version 1.0 */ -public class DefaultIntegrationFactory implements IntegrationFactory { +public class DefaultPf4JFactory implements Pf4jFactory { + + private final IntegrationConfiguration configuration; + + public DefaultPf4JFactory(IntegrationConfiguration configuration) { + this.configuration = configuration; + } @Override - public PluginManager getPluginManager(IntegrationConfiguration configuration) { + public PluginManager getPluginManager() { if(configuration == null){ throw new NullPointerException("IntegrationConfiguration is null"); } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java similarity index 43% rename from springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java rename to springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java index 92165db..2584334 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/IntegrationFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java @@ -1,20 +1,20 @@ -package com.gitee.starblues.integration; +package com.gitee.starblues.integration.pf4j; +import com.gitee.starblues.integration.application.DefaultPluginApplication; import org.pf4j.PluginManager; /** - * 集成工厂 + * Pf4j 集成工厂。获取Pf4j的PluginManager对象 * @author zhangzhuo * @version 1.0 * @see DefaultPluginApplication */ -public interface IntegrationFactory { +public interface Pf4jFactory { /** * 得到插件管理者 - * @param configuration 插件配置 * @return 插件管理者 */ - PluginManager getPluginManager(IntegrationConfiguration configuration); + PluginManager getPluginManager(); } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractPluginSpringBeanRefresh.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractPluginSpringBeanRefresh.java index 2d527b4..e0fd1b4 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractPluginSpringBeanRefresh.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractPluginSpringBeanRefresh.java @@ -1,6 +1,6 @@ package com.gitee.starblues.integration.refresh; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import java.util.List; diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java index 8cdffce..d9aee6f 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java @@ -1,6 +1,6 @@ package com.gitee.starblues.integration.refresh; -import com.gitee.starblues.integration.PluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; import com.gitee.starblues.integration.listener.PluginListener; import java.lang.reflect.ParameterizedType; diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java index 750bf77..3638eac 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/user/DefaultPluginUser.java @@ -19,8 +19,8 @@ public class DefaultPluginUser implements PluginUser{ private final PluginManager pluginManager; public DefaultPluginUser(ApplicationContext applicationContext, PluginManager pluginManager) { - Objects.requireNonNull(applicationContext); - Objects.requireNonNull(pluginManager); + Objects.requireNonNull(applicationContext, "ApplicationContext can't be null"); + Objects.requireNonNull(pluginManager, "PluginManager can't be null"); this.applicationContext = (GenericApplicationContext)applicationContext; this.pluginManager = pluginManager; } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java index d31114a..3c8ddb7 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java @@ -1,6 +1,8 @@ package com.gitee.starblues.utils; +import com.gitee.starblues.integration.IntegrationConfiguration; + import java.util.HashMap; import java.util.Map; @@ -14,8 +16,6 @@ public final class GlobalRegistryInfo { private GlobalRegistryInfo(){} - - /** * 全局插件安装次数 */ @@ -27,7 +27,6 @@ public final class GlobalRegistryInfo { private static Map extensionMap = new HashMap<>(); - /** * 添加操作插件信息 * @param pluginId 插件id -- Gitee From f6dc711307cdea939728888785c02b65090cd2cf Mon Sep 17 00:00:00 2001 From: StarBlues Date: Mon, 28 Oct 2019 17:31:48 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B0=202.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/basic-example/basic-example-main/pom.xml | 4 ++-- example/basic-example/basic-example-runner/pom.xml | 2 +- .../plugins/basic-example-plugin1/plugin.properties | 2 +- .../basic-example/plugins/basic-example-plugin1/pom.xml | 4 ++-- .../plugins/basic-example-plugin2/plugin.properties | 2 +- .../basic-example/plugins/basic-example-plugin2/pom.xml | 4 ++-- example/basic-example/plugins/pom.xml | 2 +- example/basic-example/pom.xml | 2 +- .../integration-mybatis/integration-mybatis-main/pom.xml | 9 +++++---- .../integration-mybatis-plugin-parent/pom.xml | 2 +- .../integration-mybatis-runner/pom.xml | 2 +- .../integration-mybatis-plugin1/plugin.properties | 2 +- .../plugins/integration-mybatis-plugin1/pom.xml | 6 +++--- .../integration-mybatis-plugin2/plugin.properties | 2 +- .../plugins/integration-mybatis-plugin2/pom.xml | 6 +++--- example/integration-mybatis/pom.xml | 2 +- .../integration-mybatisplus-main/pom.xml | 6 +++--- .../integration-mybatisplus-plugin/plugin.properties | 2 +- .../plugins/integration-mybatisplus-plugin/pom.xml | 2 +- example/integration-mybatisplus/pom.xml | 2 +- example/pom.xml | 2 +- pom.xml | 2 +- springboot-plugin-framework-extension/pom.xml | 2 +- .../pom.xml | 4 ++-- springboot-plugin-framework/pom.xml | 2 +- 25 files changed, 39 insertions(+), 38 deletions(-) diff --git a/example/basic-example/basic-example-main/pom.xml b/example/basic-example/basic-example-main/pom.xml index af9add2..2a61c25 100644 --- a/example/basic-example/basic-example-main/pom.xml +++ b/example/basic-example/basic-example-main/pom.xml @@ -13,13 +13,13 @@ com.gitee.starblues basic-example-main - 2.1.4-RELEASE + 2.2.0-RELEASE jar 2.7.0 1.6 - 2.1.4-RELEASE + 2.2.0-RELEASE diff --git a/example/basic-example/basic-example-runner/pom.xml b/example/basic-example/basic-example-runner/pom.xml index 51509a9..0ac04aa 100644 --- a/example/basic-example/basic-example-runner/pom.xml +++ b/example/basic-example/basic-example-runner/pom.xml @@ -14,7 +14,7 @@ com.gitee.starblues basic-example-runner - 2.1.4-RELEASE + 2.2.0-RELEASE pom diff --git a/example/basic-example/plugins/basic-example-plugin1/plugin.properties b/example/basic-example/plugins/basic-example-plugin1/plugin.properties index d9ff7d8..5090ae7 100644 --- a/example/basic-example/plugins/basic-example-plugin1/plugin.properties +++ b/example/basic-example/plugins/basic-example-plugin1/plugin.properties @@ -1,4 +1,4 @@ plugin.id=basic-example-plugin1 plugin.class=com.basic.example.plugin1.DefinePlugin -plugin.version=2.1.4-RELEASE +plugin.version=2.2.0-RELEASE plugin.provider=StarBlues \ No newline at end of file diff --git a/example/basic-example/plugins/basic-example-plugin1/pom.xml b/example/basic-example/plugins/basic-example-plugin1/pom.xml index 6343f5a..b4c1ba2 100644 --- a/example/basic-example/plugins/basic-example-plugin1/pom.xml +++ b/example/basic-example/plugins/basic-example-plugin1/pom.xml @@ -8,12 +8,12 @@ com.gitee.starblues basic-example-plugin-parent - 2.1.4-RELEASE + 2.2.0-RELEASE ../pom.xml basic-example-plugin1 - 2.1.4-RELEASE + 2.2.0-RELEASE jar diff --git a/example/basic-example/plugins/basic-example-plugin2/plugin.properties b/example/basic-example/plugins/basic-example-plugin2/plugin.properties index 96f2d22..43de2a7 100644 --- a/example/basic-example/plugins/basic-example-plugin2/plugin.properties +++ b/example/basic-example/plugins/basic-example-plugin2/plugin.properties @@ -1,4 +1,4 @@ plugin.id=basic-example-plugin2 plugin.class=com.basic.example.plugin2.DefinePlugin -plugin.version=2.1.4-RELEASE +plugin.version=2.2.0-RELEASE plugin.provider=StarBlues \ No newline at end of file diff --git a/example/basic-example/plugins/basic-example-plugin2/pom.xml b/example/basic-example/plugins/basic-example-plugin2/pom.xml index a109b8e..becb8e7 100644 --- a/example/basic-example/plugins/basic-example-plugin2/pom.xml +++ b/example/basic-example/plugins/basic-example-plugin2/pom.xml @@ -8,12 +8,12 @@ com.gitee.starblues basic-example-plugin-parent - 2.1.4-RELEASE + 2.2.0-RELEASE ../pom.xml basic-example-plugin2 - 2.1.4-RELEASE + 2.2.0-RELEASE jar diff --git a/example/basic-example/plugins/pom.xml b/example/basic-example/plugins/pom.xml index 8b8e99a..25320c5 100644 --- a/example/basic-example/plugins/pom.xml +++ b/example/basic-example/plugins/pom.xml @@ -7,7 +7,7 @@ com.gitee.starblues basic-example-plugin-parent - 2.1.4-RELEASE + 2.2.0-RELEASE pom diff --git a/example/basic-example/pom.xml b/example/basic-example/pom.xml index 07a3308..7dfaf47 100644 --- a/example/basic-example/pom.xml +++ b/example/basic-example/pom.xml @@ -6,7 +6,7 @@ com.gitee.starblues basic-example - 2.1.4-RELEASE + 2.2.0-RELEASE pom 基本案例 diff --git a/example/integration-mybatis/integration-mybatis-main/pom.xml b/example/integration-mybatis/integration-mybatis-main/pom.xml index 018e104..1c62e7d 100644 --- a/example/integration-mybatis/integration-mybatis-main/pom.xml +++ b/example/integration-mybatis/integration-mybatis-main/pom.xml @@ -14,13 +14,13 @@ com.gitee.starblues integration-mybatis-main - 2.1.4-RELEASE + 2.2.0-RELEASE jar 主程序模块 - 2.1.4-RELEASE - 2.1.4-RELEASE + 2.2.0-RELEASE + 2.2.0-RELEASE 2.0.1 2.7.0 1.6 @@ -85,7 +85,6 @@ ${swagger-bootstrap-ui.version} - org.springframework.boot spring-boot-starter-test @@ -102,6 +101,8 @@ spring-boot-maven-plugin + + repackage repackage diff --git a/example/integration-mybatis/integration-mybatis-plugin-parent/pom.xml b/example/integration-mybatis/integration-mybatis-plugin-parent/pom.xml index d15419e..a8bceb6 100644 --- a/example/integration-mybatis/integration-mybatis-plugin-parent/pom.xml +++ b/example/integration-mybatis/integration-mybatis-plugin-parent/pom.xml @@ -7,7 +7,7 @@ com.gitee.starblues integration-mybatis-plugin-parent - 2.1.4-RELEASE + 2.2.0-RELEASE pom diff --git a/example/integration-mybatis/integration-mybatis-runner/pom.xml b/example/integration-mybatis/integration-mybatis-runner/pom.xml index 2f6131a..66423b6 100644 --- a/example/integration-mybatis/integration-mybatis-runner/pom.xml +++ b/example/integration-mybatis/integration-mybatis-runner/pom.xml @@ -14,7 +14,7 @@ com.gitee.starblues integration-mybatis-runner - 2.1.4-RELEASE + 2.2.0-RELEASE jar 启动程序模块。将启动类配置到该模块下 diff --git a/example/integration-mybatis/plugins/integration-mybatis-plugin1/plugin.properties b/example/integration-mybatis/plugins/integration-mybatis-plugin1/plugin.properties index 99109b7..c909a8d 100644 --- a/example/integration-mybatis/plugins/integration-mybatis-plugin1/plugin.properties +++ b/example/integration-mybatis/plugins/integration-mybatis-plugin1/plugin.properties @@ -1,4 +1,4 @@ plugin.id=integration-mybatis-plugin1 plugin.class=com.mybatis.plugin1.ExamplePlugin1 -plugin.version=2.1.4-RELEASE +plugin.version=2.2.0-RELEASE plugin.provider=StarBlues \ No newline at end of file diff --git a/example/integration-mybatis/plugins/integration-mybatis-plugin1/pom.xml b/example/integration-mybatis/plugins/integration-mybatis-plugin1/pom.xml index af20f00..a4bf654 100644 --- a/example/integration-mybatis/plugins/integration-mybatis-plugin1/pom.xml +++ b/example/integration-mybatis/plugins/integration-mybatis-plugin1/pom.xml @@ -8,12 +8,12 @@ com.gitee.starblues integration-mybatis-plugin-parent - 2.1.4-RELEASE - ../../integration-mybatis-plugin-parent + 2.2.0-RELEASE + ../../integration-mybatis-plugin-parent/pom.xml integration-mybatis-plugin1 - 2.1.4-RELEASE + 2.2.0-RELEASE jar diff --git a/example/integration-mybatis/plugins/integration-mybatis-plugin2/plugin.properties b/example/integration-mybatis/plugins/integration-mybatis-plugin2/plugin.properties index f65a59d..e1aa830 100644 --- a/example/integration-mybatis/plugins/integration-mybatis-plugin2/plugin.properties +++ b/example/integration-mybatis/plugins/integration-mybatis-plugin2/plugin.properties @@ -1,4 +1,4 @@ plugin.id=integration-mybatis-plugin2 plugin.class=com.mybatis.plugin2.ExamplePlugin2 -plugin.version=2.1.4-RELEASE +plugin.version=2.2.0-RELEASE plugin.provider=StarBlues \ No newline at end of file diff --git a/example/integration-mybatis/plugins/integration-mybatis-plugin2/pom.xml b/example/integration-mybatis/plugins/integration-mybatis-plugin2/pom.xml index dd08cc3..9389e18 100644 --- a/example/integration-mybatis/plugins/integration-mybatis-plugin2/pom.xml +++ b/example/integration-mybatis/plugins/integration-mybatis-plugin2/pom.xml @@ -8,12 +8,12 @@ com.gitee.starblues integration-mybatis-plugin-parent - 2.1.4-RELEASE - ../../integration-mybatis-plugin-parent + 2.2.0-RELEASE + ../../integration-mybatis-plugin-parent/pom.xml integration-mybatis-plugin2 - 2.1.4-RELEASE + 2.2.0-RELEASE jar diff --git a/example/integration-mybatis/pom.xml b/example/integration-mybatis/pom.xml index 606631d..3f80dab 100644 --- a/example/integration-mybatis/pom.xml +++ b/example/integration-mybatis/pom.xml @@ -7,7 +7,7 @@ com.gitee.starblues integration-mybatis - 2.1.4-RELEASE + 2.2.0-RELEASE pom 集成mybatis案例 diff --git a/example/integration-mybatisplus/integration-mybatisplus-main/pom.xml b/example/integration-mybatisplus/integration-mybatisplus-main/pom.xml index ab42040..a9f100e 100644 --- a/example/integration-mybatisplus/integration-mybatisplus-main/pom.xml +++ b/example/integration-mybatisplus/integration-mybatisplus-main/pom.xml @@ -13,7 +13,7 @@ com.gitee.starblues - 2.1.4-RELEASE + 2.2.0-RELEASE integration-mybatisplus-main jar 集成mybatis-plus 案例--主程序 @@ -27,8 +27,8 @@ 2.0.1 3.2.0 - 2.1.4-RELEASE - 2.1.4-RELEASE + 2.2.0-RELEASE + 2.2.0-RELEASE 2.7.0 1.6 diff --git a/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/plugin.properties b/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/plugin.properties index 61c6862..3c62bc0 100644 --- a/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/plugin.properties +++ b/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/plugin.properties @@ -1,4 +1,4 @@ plugin.id=integration-mybatisplus-plugin plugin.class=com.mybatisplus.plugin.MybatisPlusPlugin -plugin.version=2.1.4-RELEASE +plugin.version=2.2.0-RELEASE plugin.provider=StarBlues \ No newline at end of file diff --git a/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/pom.xml b/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/pom.xml index ff0e50c..1eeb886 100644 --- a/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/pom.xml +++ b/example/integration-mybatisplus/plugins/integration-mybatisplus-plugin/pom.xml @@ -6,7 +6,7 @@ com.gitee.starblues integration-mybatisplus-plugin - 2.1.4-RELEASE + 2.2.0-RELEASE jar diff --git a/example/integration-mybatisplus/pom.xml b/example/integration-mybatisplus/pom.xml index 7f7bcc3..cc45b57 100644 --- a/example/integration-mybatisplus/pom.xml +++ b/example/integration-mybatisplus/pom.xml @@ -6,7 +6,7 @@ com.gitee.starblues integration-mybatisplus - 2.1.4-RELEASE + 2.2.0-RELEASE pom 集成mybatis-plus案例 diff --git a/example/pom.xml b/example/pom.xml index 42b8d7e..d2fdd98 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -6,7 +6,7 @@ com.gitee.starblues springboot-plugin-framework-example - 2.1.4-RELEASE + 2.2.0-RELEASE pom diff --git a/pom.xml b/pom.xml index 1770ff0..a279886 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.gitee.starblues springboot-plugin-framework-parent pom - 2.1.4-RELEASE + 2.2.0-RELEASE spring boot 插件开发集成包 diff --git a/springboot-plugin-framework-extension/pom.xml b/springboot-plugin-framework-extension/pom.xml index 07c05d4..898bede 100644 --- a/springboot-plugin-framework-extension/pom.xml +++ b/springboot-plugin-framework-extension/pom.xml @@ -9,7 +9,7 @@ com.gitee.starblues springboot-plugin-framework-extension pom - 2.1.4-RELEASE + 2.2.0-RELEASE spring boot 插件式开发集成包--扩展模块 diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/pom.xml b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/pom.xml index 0536374..064ddad 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/pom.xml +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/pom.xml @@ -13,7 +13,7 @@ com.gitee.starblues springboot-plugin-framework-extension-mybatis - 2.1.4-RELEASE + 2.2.0-RELEASE jar 插件扩展-spring boot mybatis 集成扩展 @@ -64,7 +64,7 @@ 3.1.0 1.6 - 2.1.4-RELEASE + 2.2.0-RELEASE 2.0.1 3.2.0 diff --git a/springboot-plugin-framework/pom.xml b/springboot-plugin-framework/pom.xml index 15a78cc..925111a 100644 --- a/springboot-plugin-framework/pom.xml +++ b/springboot-plugin-framework/pom.xml @@ -13,7 +13,7 @@ com.gitee.starblues springboot-plugin-framework jar - 2.1.4-RELEASE + 2.2.0-RELEASE spring boot 插件式开发集成包 -- Gitee From 4da25f4613d450c033cfe85aabeebbbda86c5da7 Mon Sep 17 00:00:00 2001 From: StarBlues Date: Mon, 28 Oct 2019 17:46:24 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../factory/PluginInfoContainer.java | 2 ++ .../starblues/factory/PluginRegistryInfo.java | 23 ++++++++++++++++++- .../integration/ConfigurationBuilder.java | 2 +- .../integration/PluginListenerContext.java | 4 +++- .../AbstractPluginApplication.java | 2 +- .../application/AutoPluginApplication.java | 2 +- .../application/DefaultPluginApplication.java | 2 +- .../application/PluginApplication.java | 2 +- .../listener/PluginListenerFactory.java | 1 + .../operator/DefaultPluginOperator.java | 2 +- .../integration/operator/PluginOperator.java | 2 +- .../integration/pf4j/DefaultPf4JFactory.java | 2 +- .../integration/pf4j/Pf4jFactory.java | 2 +- .../refresh/AbstractSpringBeanRefresh.java | 1 + .../starblues/utils/GlobalRegistryInfo.java | 7 ++++++ 15 files changed, 45 insertions(+), 11 deletions(-) diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginInfoContainer.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginInfoContainer.java index 404cd56..af1bb3e 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginInfoContainer.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginInfoContainer.java @@ -55,6 +55,7 @@ public class PluginInfoContainer { * 是否存在bean名称 * @param pluginId 插件id * @param beanName 注册的bean名称 + * @return true 存在。false不存在 */ public static synchronized boolean existRegisterBeanName(String pluginId, String beanName){ Set beanNames = springRegisterBeanNames.get(pluginId); @@ -68,6 +69,7 @@ public class PluginInfoContainer { /** * 是否存在bean名称 * @param beanName 注册的bean名称 + * @return true 存在。false不存在 */ public static synchronized boolean existRegisterBeanName(String beanName){ for (Set beanNames : springRegisterBeanNames.values()){ diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginRegistryInfo.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginRegistryInfo.java index 9e150d4..23ecdd1 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginRegistryInfo.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/factory/PluginRegistryInfo.java @@ -50,22 +50,38 @@ public class PluginRegistryInfo { return basePlugin; } + /** + * 添加类到类集合容器 + * @param aClass 类 + */ public void addClasses(Class aClass){ if(aClass != null){ classes.add(aClass); } } + /** + * 清除类集合容器 + */ public void cleanClasses(){ classes.clear(); } + /** + * 得到类集合容器 + * @return 类集合容器 + */ public List> getClasses(){ List> result = new ArrayList<>(); result.addAll(classes); return result; } + /** + * 添加分组的类型 + * @param key 分组key + * @param aClass 类 + */ public void addGroupClasses(String key, Class aClass){ List> classes = groupClasses.get(key); if(classes == null){ @@ -75,6 +91,11 @@ public class PluginRegistryInfo { classes.add(aClass); } + /** + * 通过分组key得到分组中的类类型 + * @param key 处理者key + * @return 类类型集合 + */ public List> getGroupClasses(String key){ List> classes = groupClasses.get(key); List> result = new ArrayList<>(); @@ -87,6 +108,7 @@ public class PluginRegistryInfo { /** * 得到插件bean注册者信息 * @param key 扩展的key + * @param 处理者类型 * @return 注册者信息 */ public T getProcessorInfo(String key){ @@ -134,5 +156,4 @@ public class PluginRegistryInfo { - } diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java index 32a6d26..ab23f57 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/ConfigurationBuilder.java @@ -9,7 +9,7 @@ import java.util.Objects; * 通过构造者进行配置插件初始化配置 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class ConfigurationBuilder extends DefaultIntegrationConfiguration{ diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginListenerContext.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginListenerContext.java index a0af247..e25e698 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginListenerContext.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/PluginListenerContext.java @@ -9,7 +9,7 @@ import java.util.List; * 插件bean监听者上下文。 * 注意: 监听者必须在初始化插件前添加,否则在初始化阶段可能无法触发添加的监听者。 * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public interface PluginListenerContext { @@ -19,9 +19,11 @@ public interface PluginListenerContext { */ void addListener(PluginListener pluginListener); + /** * 添加监听者 * @param pluginListenerClass 插件监听者Class类 + * @param 继承PluginListener的子类 */ void addListener(Class pluginListenerClass); diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java index 7b749e0..ab1fb9c 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AbstractPluginApplication.java @@ -14,7 +14,7 @@ import java.util.List; * 公用的的插件应用 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public abstract class AbstractPluginApplication implements PluginApplication { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java index 0637be9..dcba071 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/AutoPluginApplication.java @@ -10,7 +10,7 @@ import org.springframework.context.ApplicationContextAware; * 自动初始化的 PluginApplication。该PluginApplication 基于 Spring InitializingBean 自动初始化插件。 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class AutoPluginApplication extends DefaultPluginApplication implements PluginApplication, InitializingBean, ApplicationContextAware { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java index 6da67e5..882c753 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/DefaultPluginApplication.java @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * 默认的插件 PluginApplication * @author zhangzhuo - * @version 2.0.2 + * @version 2.2.0 */ public class DefaultPluginApplication extends AbstractPluginApplication { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java index b61ea77..233475f 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/application/PluginApplication.java @@ -10,7 +10,7 @@ import org.springframework.context.ApplicationContext; /** * 插件应用。 * @author zhangzhuo - * @version 2.0.2 + * @version 2.2.0 */ public interface PluginApplication extends PluginListenerContext { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java index 6c3e9d0..629eac2 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/listener/PluginListenerFactory.java @@ -62,6 +62,7 @@ public class PluginListenerFactory implements PluginListener{ /** * 添加监听者 * @param pluginListenerClass 插件监听者Class类 + * @param 插件监听者类。继承 PluginListener */ public void addPluginListener(Class pluginListenerClass){ if(pluginListenerClass != null){ diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java index 8c4b3e4..6070a4b 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/DefaultPluginOperator.java @@ -34,7 +34,7 @@ import java.util.stream.Collectors; /** * 默认的插件操作者 * @author zhangzhuo - * @version 2.1.0 + * @version 2.2.0 */ public class DefaultPluginOperator implements PluginOperator { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java index 3fbc42d..6e52150 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/operator/PluginOperator.java @@ -12,7 +12,7 @@ import java.util.Set; /** * 操作插件的接口 * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 * @see DefaultPluginOperator */ public interface PluginOperator { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java index f6fe977..e52cf7c 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/DefaultPf4JFactory.java @@ -10,7 +10,7 @@ import java.util.Objects; /** * 默认的插件集成工厂 * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class DefaultPf4JFactory implements Pf4jFactory { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java index 2584334..341e2ed 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/pf4j/Pf4jFactory.java @@ -6,7 +6,7 @@ import org.pf4j.PluginManager; /** * Pf4j 集成工厂。获取Pf4j的PluginManager对象 * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 * @see DefaultPluginApplication */ public interface Pf4jFactory { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java index d9aee6f..8cee174 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/integration/refresh/AbstractSpringBeanRefresh.java @@ -64,6 +64,7 @@ public abstract class AbstractSpringBeanRefresh implements PluginListener { /** * 刷新bean + * @return 返回刷新后的Bean集合 */ protected List refresh(){ return pluginApplication diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java index 3c8ddb7..1dd3a88 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java @@ -30,6 +30,8 @@ public final class GlobalRegistryInfo { /** * 添加操作插件信息 * @param pluginId 插件id + * @param operatorType 操作类型 + * @param isLock 是否加锁 */ public static synchronized void addOperatorPluginInfo(String pluginId, PluginOperatorInfo.OperatorType operatorType, @@ -44,6 +46,11 @@ public final class GlobalRegistryInfo { } + /** + * 设置操作插件的信息 + * @param pluginId 插件id + * @param isLock 是否加锁 + */ public static synchronized void setOperatorPluginInfo(String pluginId, boolean isLock){ PluginOperatorInfo operatorPluginInfo = operatorPluginInfos.get(pluginId); if(operatorPluginInfo != null){ -- Gitee From 4923a08fd77426c3c505a3fe4245ec0aff0a9d7d Mon Sep 17 00:00:00 2001 From: StarBlues Date: Mon, 28 Oct 2019 17:49:34 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../starblues/extension/mybatis/PluginMybatisXmlLoader.java | 2 +- .../starblues/extension/mybatis/PluginMybatisXmlProcessor.java | 2 +- .../starblues/extension/mybatis/utils/MybatisXmlProcess.java | 2 +- .../com/gitee/starblues/loader/PluginResourceLoadFactory.java | 2 +- .../java/com/gitee/starblues/loader/PluginResourceLoader.java | 2 +- .../main/java/com/gitee/starblues/loader/ResourceWrapper.java | 2 +- .../java/com/gitee/starblues/loader/load/PluginClassLoader.java | 2 +- .../com/gitee/starblues/loader/load/PluginConfigFileLoader.java | 2 +- .../src/main/java/com/gitee/starblues/realize/BasePlugin.java | 2 +- .../main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java | 2 +- .../main/java/com/gitee/starblues/utils/PluginOperatorInfo.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java index 6d2fb12..ba805ff 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlLoader.java @@ -20,7 +20,7 @@ import java.util.*; * 定制插件 Mybatis xml 加载者 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class PluginMybatisXmlLoader implements PluginResourceLoader { diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java index bb033e6..f6b237e 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/PluginMybatisXmlProcessor.java @@ -17,7 +17,7 @@ import java.util.List; * mybatis xml 处理者 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class PluginMybatisXmlProcessor implements PluginPipeProcessorExtend { diff --git a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java index 4e06e1a..5ed3265 100644 --- a/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java +++ b/springboot-plugin-framework-extension/springboot-plugin-framework-extension-mybatis/src/main/java/com/gitee/starblues/extension/mybatis/utils/MybatisXmlProcess.java @@ -19,7 +19,7 @@ import java.util.concurrent.ConcurrentHashMap; * mybatis xml 操作者 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class MybatisXmlProcess { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java index 62472e0..b7f7fe2 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoadFactory.java @@ -18,7 +18,7 @@ import java.util.concurrent.ConcurrentHashMap; * 插件资源加载者 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class PluginResourceLoadFactory { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java index 372d179..567d748 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/PluginResourceLoader.java @@ -10,7 +10,7 @@ import java.util.List; * 插件资源加载者统一定义的接口 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public interface PluginResourceLoader { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java index 1bc0b38..74749ff 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/ResourceWrapper.java @@ -8,7 +8,7 @@ import java.util.*; * 资源包装类 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class ResourceWrapper { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java index a742309..6b6e87b 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginClassLoader.java @@ -18,7 +18,7 @@ import java.util.List; * 插件类文件加载者 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class PluginClassLoader implements PluginResourceLoader { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java index 04219ce..5f2bdc2 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/loader/load/PluginConfigFileLoader.java @@ -18,7 +18,7 @@ import java.util.List; * 插件配置文件加载者 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class PluginConfigFileLoader implements PluginResourceLoader { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java index 4ffd226..40683ba 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/realize/BasePlugin.java @@ -7,7 +7,7 @@ import org.pf4j.PluginWrapper; /** * 插件包要继承的抽象类 * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public abstract class BasePlugin extends Plugin { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java index 1dd3a88..0522ca0 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/GlobalRegistryInfo.java @@ -10,7 +10,7 @@ import java.util.Map; * 全局注册信息 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public final class GlobalRegistryInfo { diff --git a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/PluginOperatorInfo.java b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/PluginOperatorInfo.java index 9f7d07e..f503465 100644 --- a/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/PluginOperatorInfo.java +++ b/springboot-plugin-framework/src/main/java/com/gitee/starblues/utils/PluginOperatorInfo.java @@ -6,7 +6,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * 操作插件信息。为了解决连续上传安装后, 停止后, 无法启动的问题。 * * @author zhangzhuo - * @version 1.0 + * @version 2.2.0 */ public class PluginOperatorInfo { -- Gitee