Set context ClassLoader to plugin ClassLoader for correct class loading operations (#7725)

#### What type of PR is this?

/kind bug
/area plugin
/milestone 2.21.x

#### What this PR does / why we need it:

This PR fixes the problem that loading resources from class path during static initialization doesn't work.

#### Does this PR introduce a user-facing change?

```release-note
修复部分场景下无法正常启动插件的问题
```
pull/7726/head
John Niang 2025-08-29 11:30:15 +08:00 committed by GitHub
parent a32cd4b551
commit 2a37366c92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 0 deletions

View File

@ -70,6 +70,12 @@ public class DefaultPluginApplicationContextFactory implements PluginApplication
var pluginWrapper = pluginManager.getPlugin(pluginId);
var classLoader = pluginWrapper.getPluginClassLoader();
// Set the context ClassLoader to the plugin ClassLoader to ensure that
// any class loading operations performed by the context (e.g., initializing
// bean definitions, loading class resources during static initialization)
// use the correct ClassLoader.
Thread.currentThread().setContextClassLoader(classLoader);
/*
* Manually creating a BeanFactory and setting the plugin's ClassLoader is necessary
* to ensure that conditional annotations (e.g., @ConditionalOnClass) within the plugin
@ -182,6 +188,7 @@ public class DefaultPluginApplicationContextFactory implements PluginApplication
log.debug("Refreshing application context for plugin {}", pluginId);
sw.start("Refresh");
context.refresh();
sw.stop();
log.debug("Refreshed application context for plugin {}", pluginId);

View File

@ -1,5 +1,6 @@
package run.halo.app.plugin;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
@ -39,6 +40,8 @@ class DefaultPluginApplicationContextFactoryTest {
when(pluginManager.getPlugin("fake-plugin")).thenReturn(pw);
var context = factory.create("fake-plugin");
assertEquals(pw.getPluginClassLoader(), Thread.currentThread().getContextClassLoader());
assertInstanceOf(PluginApplicationContext.class, context);
assertNotNull(context.getBeanProvider(SearchService.class).getIfUnique());
assertNotNull(context.getBeanProvider(PluginsRootGetter.class).getIfUnique());