启动时读取ConfigurationProperties正常,Bean调用时却显示null
问题排查与解决
问题现象
将Mongo配置属性存储在外部application.properties文件中,通过自定义MongoProperties类读取。启动应用时,getDatabase()方法能正确输出配置的属性值,但在控制器调用MongoGeneral中的SimpleMongoClientDatabaseFactory Bean时,属性值变为null,仅硬编码配置能正常工作。
核心原因
手动创建新的Spring容器实例导致配置隔离:
- 在
UserController的getCollections方法中,通过new AnnotationConfigApplicationContext(MongoGeneral.class)创建了一个全新的Spring容器,这个容器与Spring Boot启动的主容器完全独立,无法获取主容器中已加载的配置属性,因此MongoProperties在新容器中未被正确初始化,属性值为null。 - 启动时
getDatabase()能正常输出,是因为此时是主容器初始化MongoGeneralBean时调用的,MongoProperties已被正确加载配置。
解决方案
移除手动创建容器的代码,直接通过Spring依赖注入获取所需Bean,利用主容器的配置上下文。
修正后的UserController代码
package com.mistermorse.flawlessbeansjavaspringapi.controller; import com.mistermorse.flawlessbeansjavaspringapi.config.MongoProperties; import com.mongodb.client.MongoIterable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { private final SimpleMongoClientDatabaseFactory mongoDbFactory; private final MongoProperties mongoProperties; // 直接注入主容器中的Bean,无需手动创建新容器 @Autowired public UserController(SimpleMongoClientDatabaseFactory mongoDbFactory, MongoProperties mongoProperties) { this.mongoDbFactory = mongoDbFactory; this.mongoProperties = mongoProperties; } @GetMapping("/collections") public MongoIterable<String> getCollections() { // 使用注入的Bean直接获取配置好的数据库 return mongoDbFactory.getMongoDatabase().listCollectionNames(); } }
优化后的MongoGeneral代码(替换硬编码URI为配置属性)
package com.mistermorse.flawlessbeansjavaspringapi.config; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.lang.NonNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; @Configuration public class MongoGeneral extends AbstractMongoClientConfiguration { private final MongoProperties mongoProperties; @Autowired public MongoGeneral(MongoProperties mongoProperties) { this.mongoProperties = mongoProperties; } @Override @NonNull public String getDatabaseName() { System.out.println("Name: " + this.mongoProperties.getDatabase()); return this.mongoProperties.getDatabase(); } @Override @NonNull public MongoClient mongoClient() { // 使用配置文件中的URI,不再硬编码 return MongoClients.create(mongoProperties.getUri()); } @Bean @NonNull @Override public SimpleMongoClientDatabaseFactory mongoDbFactory() { return new SimpleMongoClientDatabaseFactory(mongoClient(), getDatabaseName()); } }
额外说明
- 移除了
UserController和MongoGeneral中的@EnableConfigurationProperties,因为主类FlawlessBeansJavaSpringApiApplication已添加@ConfigurationPropertiesScan,会自动扫描并注册MongoProperties。 - 避免手动创建
ApplicationContext,Spring Boot的核心优势之一就是依赖注入,直接注入Bean能保证使用的是主容器中已初始化的实例,配置属性自然能正确读取。
内容的提问来源于stack exchange,提问作者rainydaymatt
相关产品推荐
相关产品推荐

