Wildfly部署的JEE应用整合Spring:属性文件加载异常触发问题
解决Spring属性加载失效与文件缺失校验问题
嘿,你的问题核心在于Spring上下文没在JEE/CDI环境里被正确初始化——虽然CDI把Config实例注入到了Consumer里,但Spring的@PropertySource和@Value注解完全没生效,相当于只是new了个空的Config对象,这就是hostName一直返回null的原因,而且文件不存在也没抛异常,因为Spring的属性加载流程根本没启动起来。
下面是一步步的修复方案:
1. 补全Spring与CDI整合的依赖
如果用Maven,先确保引入了Spring上下文和CDI整合的关键依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>你的Spring版本,比如5.3.24</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>同上版本</version> </dependency>
2. 修改Config类,强制校验属性文件存在
更新你的Config类,添加PropertySourcesPlaceholderConfigurer Bean,并设置ignoreResourceNotFound=false,这样找不到文件时Spring会直接抛异常:
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @Configuration @PropertySource(value = "classpath:test.properties", ignoreResourceNotFound = false) public class Config { @Value("${hostName}") private String hostName; // 必须注册这个静态Bean来激活@Value的属性解析逻辑 @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); // 强制要求属性文件必须存在,不存在则启动失败 configurer.setIgnoreResourceNotFound(false); return configurer; } public String getHostName() { return hostName; } }
3. 在CDI环境中初始化Spring上下文
创建一个CDI的生产者类,用来启动Spring上下文,并把Spring管理的Config实例暴露给CDI容器:
import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @ApplicationScoped public class SpringCdiBridge { private AnnotationConfigApplicationContext springContext; @PostConstruct public void initSpringContext() { // 加载Spring配置类,启动Spring上下文 springContext = new AnnotationConfigApplicationContext(Config.class); // 确保应用关闭时Spring上下文也能正常销毁 springContext.registerShutdownHook(); } // 把Spring管理的Config实例作为CDI Bean提供出去 @Produces @ApplicationScoped public Config getSpringConfig() { return springContext.getBean(Config.class); } }
这个类的作用是:在CDI应用启动时初始化Spring上下文,然后把Spring处理过的Config实例交给CDI,这样Consumer里@Inject的就不再是CDI自己创建的空对象,而是已经完成属性注入的Spring Bean。
4. 验证效果
- 把
test.properties放到src/main/resources下(确保在类路径中),写入内容:hostName=my-wildfly-host,启动WildFly后调用Consumer.test(),会返回test +my-wildfly-host。 - 删掉
test.properties再启动,Spring会直接抛出FileNotFoundException,正好满足你验证文件存在性的需求。
重要提醒
别给Config类加CDI的注解(比如@Named),否则CDI会跳过Spring的逻辑自己创建实例,属性注入还是会失效。
内容的提问来源于stack exchange,提问作者Alexandr
相关产品推荐
相关产品推荐

