refactor: support extending jar directories for plugin class loader (#3108)

#### What type of PR is this?
/kind improvement
/area core
/milestone 2.2.x

#### What this PR does / why we need it:
修复引入外部依赖的插件以开发模式启动时会出现 NoClassDefFoundError 的问题
see #3107 for more detail.

#### Which issue(s) this PR fixes:
Fixes #3107

#### Special notes for your reviewer:
how to test it?
以插件 development 模式启动以下两个插件观察是否正常启动:
- https://github.com/halo-sigs/plugin-s3
- https://github.com/halo-sigs/plugin-alioss

期望没有 `Caused by: java. lang. NoClassDefFoundEenon` 错误,且插件正确启动。

/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?
```release-note
修复引入外部依赖的插件以开发模式启动时会出现 NoClassDefFoundError 的问题
```
pull/3130/head
guqing 2023-01-09 16:16:39 +08:00 committed by GitHub
parent 9740de8d4a
commit 64ed793efd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 14 deletions

View File

@ -107,17 +107,30 @@ public class PluginAutoConfiguration {
} else { } else {
return new CompoundPluginLoader() return new CompoundPluginLoader()
.add(new DevelopmentPluginLoader(this) { .add(new DevelopmentPluginLoader(this) {
@Override
protected PluginClassLoader createPluginClassLoader(Path pluginPath,
PluginDescriptor pluginDescriptor) {
return new PluginClassLoader(pluginManager, pluginDescriptor,
getClass().getClassLoader(), ClassLoadingStrategy.APD);
}
@Override @Override
public ClassLoader loadPlugin(Path pluginPath, public ClassLoader loadPlugin(Path pluginPath,
PluginDescriptor pluginDescriptor) { PluginDescriptor pluginDescriptor) {
PluginClassLoader pluginClassLoader = if (pluginProperties.getClassesDirectories() != null) {
new PluginClassLoader(pluginManager, pluginDescriptor, for (String classesDirectory :
getClass().getClassLoader(), ClassLoadingStrategy.APD); pluginProperties.getClassesDirectories()) {
pluginClasspath.addClassesDirectories(classesDirectory);
loadClasses(pluginPath, pluginClassLoader); }
loadJars(pluginPath, pluginClassLoader); }
if (pluginProperties.getLibDirectories() != null) {
return pluginClassLoader; for (String libDirectory :
pluginProperties.getLibDirectories()) {
pluginClasspath.addJarsDirectories(libDirectory);
}
}
return super.loadPlugin(pluginPath, pluginDescriptor);
} }
}, this::isDevelopment) }, this::isDevelopment)
.add(new JarPluginLoader(this) { .add(new JarPluginLoader(this) {

View File

@ -17,6 +17,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@Data @Data
@ConfigurationProperties(prefix = "halo.plugin") @ConfigurationProperties(prefix = "halo.plugin")
public class PluginProperties { public class PluginProperties {
public static final String GRADLE_LIBS_DIR = "build/libs";
/** /**
* Auto start plugin when main app is ready. * Auto start plugin when main app is ready.
@ -53,7 +54,7 @@ public class PluginProperties {
/** /**
* Extended Plugin Jar Directory. * Extended Plugin Jar Directory.
*/ */
private List<String> libDirectories = new ArrayList<>(); private List<String> libDirectories = new ArrayList<>(List.of(GRADLE_LIBS_DIR));
/** /**
* Runtime Modedevelopment/deployment. * Runtime Modedevelopment/deployment.

View File

@ -19,11 +19,6 @@ halo:
super-admin-password: admin super-admin-password: admin
plugin: plugin:
runtime-mode: development # development, deployment runtime-mode: development # development, deployment
classes-directories:
- "build/classes"
- "build/resources"
lib-directories:
- "libs"
work-dir: ${user.home}/halo2-dev work-dir: ${user.home}/halo2-dev
logging: logging:
level: level: