构造注入时Autowired字段为空,应用启动报NPE问题求助
问题背景与现象
在构造注入场景下,所需的Autowired字段未能及时完成注入。应用启动时,由于MigrationConfig的依赖链需要serverProperties() Bean,线程进入该方法时,ServerConfig的Autowired字段metricsProperties尚未初始化,导致抛出空指针异常(NPE)。若注释掉MigrationConfig,应用启动时serverProperties()能正常注入依赖,无异常。
相关代码示例
ServerConfig配置类
@Configuration @EnableScheduling @Import({ MigrationConfig.class, }) @EnableConfigurationProperties({ MetricsProperties.class, }) public class ServerConfig extends AbstractConfig implements SchedulingConfigurer { @Autowired private MigrationConfig migrationConfig; @Autowired private MetricsProperties metricsProperties; @Primary @Bean public ServerProperties serverProperties() { ServerProperties props = new ServerProperties(env, .., metricsProperties); //该类toString()方法调用metricsProperties时抛出NPE return props; } .... }
MigrationConfig配置类
@Configuration public class MigrationConfig { ... @Autowired private Repository repository; //该依赖最终需要serverProperties() Bean .... }
MetricsProperties类
@Getter @Setter @ConfigurationProperties(prefix = "csm.metrics") public class MetricsProperties { .... }
解决方案
方案一:方法参数注入替代字段注入
修改serverProperties()方法,将MetricsProperties作为方法参数传入,Spring会自动解析并注入该依赖,绕过字段未初始化的问题:@Primary @Bean public ServerProperties serverProperties(MetricsProperties metricsProperties) { ServerProperties props = new ServerProperties(env, .., metricsProperties); return props; }做完这个修改后,可以直接删除
ServerConfig中@Autowired private MetricsProperties metricsProperties;这个字段,减少冗余的字段注入。方案二:延迟加载打破循环依赖
当前ServerConfig通过@Import加载MigrationConfig,同时MigrationConfig依赖的Repository又需要serverProperties()Bean,ServerConfig还注入了MigrationConfig,形成了循环依赖。可以给MigrationConfig中的Repository添加@Lazy注解,延迟其初始化时机:@Configuration public class MigrationConfig { @Autowired @Lazy private Repository repository; // ... }延迟加载会让
Repository的初始化推迟到第一次实际使用时,避免在启动阶段提前触发对serverProperties()的调用,从而避开字段未初始化的窗口。方案三:重构配置类拆分循环链
将serverProperties()Bean的定义抽离到独立的配置类中,让这个新类只依赖必要的Environment和MetricsProperties,不涉及MigrationConfig:@Configuration public class ServerPropertiesConfig { @Autowired private Environment env; @Primary @Bean public ServerProperties serverProperties(MetricsProperties metricsProperties) { return new ServerProperties(env, .., metricsProperties); } }之后在
ServerConfig中@Import这个新配置类,移除原有的serverProperties()方法;MigrationConfig正常依赖Repository即可,这样就彻底打破了原来的循环依赖链。
内容的提问来源于stack exchange,提问作者Denise

