Spring Boot中@ConfigurationProperties对象返回null问题排查与解决
问题原因分析
这个问题我之前也踩过坑,核心原因是拦截器的初始化时机和Spring依赖注入的时机不匹配,导致Spring没法给你的HeaderInterceptor注入DomainProperties实例,具体拆解两点:
- 拦截器的加载优先级更高:Spring MVC在初始化
DispatcherServlet阶段就会创建并注册拦截器,如果你的拦截器是手动new出来的(不是Spring容器管理的Bean),Spring根本不知道这个实例的存在,自然没法给它注入依赖,最终domainProperties就会是null。 - 你的
HeaderInterceptor未被Spring托管:从代码看,你没有给拦截器添加@Component或其他Spring Bean注解,Spring不会把它纳入容器管理,也就无法触发自动注入逻辑。
解决方法
这里提供两种最常用的解决方案,你可以根据自己的场景选择:
方案一:把拦截器交给Spring容器管理(推荐)
这种方式让Spring全程托管拦截器的生命周期,自动处理依赖注入:
- 给
HeaderInterceptor添加@Component注解,标记为Spring Bean:
@Component // 新增该注解 public class HeaderInterceptor extends HandlerInterceptorAdapter { @Autowired private DomainProperties domainProperties; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { List<String> domainList= domainProperties.getDomainMap().values().stream().collect(Collectors.toList()); domainList.stream().forEach(domain -> response.addHeader("Access-Control-Allow-Origin", domain)); return super.preHandle(request, response, handler); } }
- 在WebMvc配置类中,通过
@Autowired注入拦截器实例并注册:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private HeaderInterceptor headerInterceptor; // 从Spring容器获取实例 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(headerInterceptor) .addPathPatterns("/**"); // 根据你的业务需求配置拦截路径 } }
方案二:手动给拦截器注入依赖(适合不想托管拦截器的场景)
如果不想把拦截器交给Spring管理,可以在配置类中手动创建实例并传入依赖:
- 修改
HeaderInterceptor,改用构造器注入(比Setter注入更安全,避免空指针):
public class HeaderInterceptor extends HandlerInterceptorAdapter { private final DomainProperties domainProperties; // 构造器注入依赖 public HeaderInterceptor(DomainProperties domainProperties) { this.domainProperties = domainProperties; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { List<String> domainList= domainProperties.getDomainMap().values().stream().collect(Collectors.toList()); domainList.stream().forEach(domain -> response.addHeader("Access-Control-Allow-Origin", domain)); return super.preHandle(request, response, handler); } }
- 在WebMvc配置类中手动创建拦截器并传入依赖:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private DomainProperties domainProperties; @Override public void addInterceptors(InterceptorRegistry registry) { // 手动创建拦截器并传入依赖 HeaderInterceptor headerInterceptor = new HeaderInterceptor(domainProperties); registry.addInterceptor(headerInterceptor) .addPathPatterns("/**"); } }
额外注意点
你的DomainProperties配置是没问题的:@Data @Component @ConfigurationProperties("app.cors")这个组合可以正确绑定application.properties中的配置到domainMap里,只要配置文件格式正确,就可以正常读取。
内容的提问来源于stack exchange,提问作者Bali
相关产品推荐
相关产品推荐

