我有一个带有层树的JPMS应用程序.在Layer C上,我需要创建Spring上下文,而Spring框架位于Layer B上:

boot layer
  |- Layer B with Spring framework.
       |- Layer C where I need to create my context

组件:

@Component
public class ApplicationContextHolder implements ApplicationContextAware {

    private static ConfigurableApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHolder.applicationContext = (ConfigurableApplicationContext) applicationContext;
    }

    public static ConfigurableApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

请注意,情况并非如此.

@Configuration
@ComponentScan(basePackageClasses = {
    ApplicationContextHolder.class
})
public class ContextConfig {

}

创建上下文:

    System.out.println("ThreadContextClassLoadere:" + Thread.currentThread().getContextClassLoader());
    System.out.println("This classLoader:" + this.getClass().getClassLoader());
    var clazz = this.getClass().getClassLoader().loadClass("org.springframework.context.ApplicationContextAware");
    System.out.println("RESULT:" + clazz);
    iocContext = new  AnnotationConfigApplicationContext();
    iocContext.register(ContextConfig.class);
    iocContext.setClassLoader(this.getClass().getClassLoader());
    iocContext.refresh();

结果:

ThreadContextClassLoadere:jdk.internal.loader.Loader@63fcbf75
This classLoader:jdk.internal.loader.Loader@63fcbf75
RESULT:interface org.springframework.context.ApplicationContextAware

Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.foo.ContextConfig]
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:178)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:415)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:287)
    at spring.context@6.0.13/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344)
    at spring.context@6.0.13/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)
    at spring.context@6.0.13/org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:779)
    at spring.context@6.0.13/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
        ....
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/context/ApplicationContextAware.class] cannot be opened because it does not exist
    at spring.core@6.0.13/org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:211)
    at spring.core@6.0.13/org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:54)
    at spring.core@6.0.13/org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:48)
    at spring.core@6.0.13/org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
    at spring.core@6.0.13/org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:122)
    at spring.core@6.0.13/org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:613)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getInterfaces(ConfigurationClassParser.java:939)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.processInterfaces(ConfigurationClassParser.java:379)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:325)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:243)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:188)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:297)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:243)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:196)
    at spring.context@6.0.13/org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:164)
    ... 16 more

据我所知(我可能是错的)Spring使用其他类加载器.有人能告诉我怎么修吗?

推荐答案

我解决了这个问题.

Spring通过getResourceAsStream()加载类,默认情况下使用ClassPathResourceclassLoader.getResourceAsStream(this.absolutePath).但是,它不适用于JPMS应用程序.要使其正常工作,需要使用ModuleResource(在Spring6.1中添加),而不是ClassPathResource.

因此,有必要创建自定义ResourceLoader,它将使用ModuleResource将其添加到上下文:

var iocContext = new  AnnotationConfigApplicationContext();
...
var myModuleResourceLoader = ....
iocContext.setResourceLoader(myModuleResourceLoader);
iocContext.refresh();

Java相关问答推荐

Selenium Java:无法访问IFRAME内部的元素

表格栏上的事件过滤器在PFA中不起作用

Mongo DB Bson和Java:在子文档中添加和返回仅存在于父文档中的字段?

当我用OkHttpClient重写shouldInterceptRequest来发布数据时,Android WebView正在以纯HTML加载URL内容

使用联接和分页的SpringBoot Spring数据JPA

Java 21 struct 化连接货币,需要可预知的子任务异常排序

使用REST客户端和对象映射器从字符串反序列化Json

相同的Java SerializedLambda为implMethodKind返回不同的结果

如何获取Instant#of EpochSecond(?)的最大值

用户填充的数组列表永不结束循环

使用PDFBox从PDF中删除图像

如何从日志(log)行中删除包名称?

在执行流和相关操作时,使用Java泛型为2个方法执行相同的操作,但对象不同

如何在JavaFX中制作鼠标透明stage

Instancio未在日志(log)中显示测试失败消息

JPA无手术同品种器械可能吗?

通过/失败的参数化junit测试方法执行数

具有多个分析模式的复杂分隔字符串的正则表达式

在Spring Boot中使用咖啡因进行缓存

字符串的Gzip压缩在java11和java17中给出了不同的结果