Spring Boot 3.1.4中ConfigurationProperties自动注入实例为空的解决方案
Spring Boot 3.1.4中@Autowired注入ConfigurationProperties类为null的解决方法
问题描述
在Spring Boot 3.1.4版本中,实现了标注@ConfigurationProperties的MdcConfig配置类,调试确认其setter方法可正确读取配置文件值,但在SomeClass中通过@Autowired注入该类时,实例始终为null。尝试过构造函数实例化(得到非Spring管理实例,无法获取配置)、添加@PostConstruct注解等方式,均未解决问题。
原因分析
这类问题通常源于以下场景:
SomeClass的实例化时机早于MdcConfig被Spring容器管理的时机,导致注入时Bean尚未初始化SomeClass并非由Spring容器创建(比如手动new实例),Spring无法完成依赖注入- 若
SomeClass继承自第三方类,可能存在Spring代理或实例化逻辑的特殊处理,导致自动注入失效
解决方法
方法1:实现ApplicationContextAware接口(已验证可行)
通过让SomeClass实现ApplicationContextAware接口,直接从Spring上下文获取MdcConfig的管理实例,确保拿到的是已加载配置的Bean。
方法2:规范依赖注入(推荐方式)
若SomeClass是Spring管理的Bean(标注@Component),可尝试以下调整:
- 确认
@ConfigurationPropertiesScan的包路径准确覆盖MdcConfig所在包,保证配置类被Spring扫描到 - 使用构造函数注入替代字段注入:Spring官方推荐构造函数注入,能避免循环依赖和注入时机问题
- 若
SomeClass由第三方框架实例化,需通过Spring的BeanPostProcessor或手动注册Bean的方式,让Spring接管其依赖管理
代码示例
MdcConfig配置类
import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.List; import java.util.Map; @ConfigurationProperties("path.in.config") public class MdcConfig { private List<String> allowedItems; private Map<String, String> replacementItems; public List<String> getAllowedItems() { return allowedItems; } public void setAllowedItems(List<String> allowedItems) { this.allowedItems = allowedItems; } public Map<String, String> getReplacementItems() { return replacementItems; } public void setReplacementItems(Map<String, String> replacementItems) { this.replacementItems = replacementItems; } }
主应用启动类
@SpringBootApplication @ConfigurationPropertiesScan("path.to.my.config.class") public class Application implements CommandLineRunner { public static void main(final String[] args) { SpringApplication application = new SpringApplication(Application.class); application.addInitializers(new ConfigurationInitializer()); application.run(args); } }
修改后的SomeClass(ApplicationContextAware实现)
@Data @Slf4j @Component public class SomeClass extends SomeOtherClass<ILoggingEvent> implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) { SomeClass.applicationContext = applicationContext; } @Override protected void append(ILoggingEvent event) { try { MdcConfig mdcConfig = applicationContext.getBean(MdcConfig.class); List<String> mdcAllowedItems = mdcConfig.getAllowedItems(); // 业务逻辑处理 } catch (Exception e) { log.error("MdcConfig is not found in ApplicationContext."); } } }
构造函数注入示例(推荐)
@Data @Slf4j @Component public class SomeClass extends SomeOtherClass<ILoggingEvent> { private final MdcConfig mdcConfig; // 构造函数注入 public SomeClass(MdcConfig mdcConfig) { this.mdcConfig = mdcConfig; } @Override protected void append(ILoggingEvent event) { List<String> mdcAllowedItems = mdcConfig.getAllowedItems(); // 业务逻辑处理 } }
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

