Spring Boot 2.5.5中@Value注入静态变量返回Null问题求助
Spring @Value注入静态变量为空的问题
尝试通过Spring @Value注解将配置属性注入到静态变量中,但获取到的均为Null值,多种配置方案都无效,此前功能运行正常,不清楚哪项改动导致故障。
问题代码
Java类代码
@Component @ConditionalOnProperty(prefix = "studioghibli", name = "get") public class StudioGhibliRestService { @Value("${studioghibli.basepath}") private static String BASE_PATH; @Value("${studioghibli.path}") private static String PATH; @Value("${studioghibli.protocol:http}") private static String PROTOCOL; @Value("${studioghibli.host}") private static String HOST; private static String BASE_URI = PROTOCOL.concat("://").concat(HOST).concat(BASE_PATH).concat(PATH); @Autowired StudioGhibliRestConnector connector; public List<StudioGhibliFilmDTO> findAllFilms() throws SipadContenziosoInternalException { var response = connector.doGet(BASE_URI, null, null); if (!response.getStatusCode().is2xxSuccessful() || !response.hasBody()) { throw new SipadContenziosoInternalException(Errore.INTERNAL_REST_ERROR, "FindAll(), microservizio ".concat(BASE_URI), null); } return (List<StudioGhibliFilmDTO>) response.getBody(); } }
该类标注了@Component注解(作为Service层用于业务逻辑中的REST调用),同时标注了@ConditionalOnProperty注解。启动时调试显示PROTOCOL值为Null,直接触发空指针异常。
配置文件(application-dev.properties)
studioghibli.get studioghibli.protocol=https studioghibli.host=ghibliapi.herokuapp.com studioghibli.basepath=/ studioghibli.path=/films
问题原因
Spring的依赖注入是针对实例对象的,@Value注解无法直接作用于静态变量——静态变量属于类而非实例,Spring在创建类实例、完成依赖注入之前,静态变量就已经完成了初始化(比如代码中的BASE_URI会在类加载时就执行拼接,此时所有静态变量还未被注入值,必然为Null)。
解决方案
方案1:通过实例变量接收注入,初始化阶段赋值给静态变量
利用@PostConstruct注解,在实例初始化完成后,将注入到实例变量的值赋值给静态变量,再拼接BASE_URI:
@Component @ConditionalOnProperty(prefix = "studioghibli", name = "get") public class StudioGhibliRestService { private static String BASE_PATH; private static String PATH; private static String PROTOCOL; private static String HOST; private static String BASE_URI; @Value("${studioghibli.basepath}") private String basePath; @Value("${studioghibli.path}") private String path; @Value("${studioghibli.protocol:http}") private String protocol; @Value("${studioghibli.host}") private String host; @Autowired StudioGhibliRestConnector connector; @PostConstruct public void init() { BASE_PATH = basePath; PATH = path; PROTOCOL = protocol; HOST = host; BASE_URI = PROTOCOL.concat("://").concat(HOST).concat(BASE_PATH).concat(PATH); } public List<StudioGhibliFilmDTO> findAllFilms() throws SipadContenziosoInternalException { var response = connector.doGet(BASE_URI, null, null); if (!response.getStatusCode().is2xxSuccessful() || !response.hasBody()) { throw new SipadContenziosoInternalException(Errore.INTERNAL_REST_ERROR, "FindAll(), microservizio ".concat(BASE_URI), null); } return (List<StudioGhibliFilmDTO>) response.getBody(); } }
方案2:通过实例setter方法注入静态变量
为每个静态变量编写非静态的setter方法,并在setter上添加@Value注解,同时在所有值注入完成后更新BASE_URI:
@Component @ConditionalOnProperty(prefix = "studioghibli", name = "get") public class StudioGhibliRestService { private static String BASE_PATH; private static String PATH; private static String PROTOCOL; private static String HOST; private static String BASE_URI; @Autowired StudioGhibliRestConnector connector; @Value("${studioghibli.basepath}") public void setBasePath(String basePath) { BASE_PATH = basePath; updateBaseUri(); } @Value("${studioghibli.path}") public void setPath(String path) { PATH = path; updateBaseUri(); } @Value("${studioghibli.protocol:http}") public void setProtocol(String protocol) { PROTOCOL = protocol; updateBaseUri(); } @Value("${studioghibli.host}") public void setHost(String host) { HOST = host; updateBaseUri(); } private void updateBaseUri() { // 确保所有变量都已注入后再拼接 if (PROTOCOL != null && HOST != null && BASE_PATH != null && PATH != null) { BASE_URI = PROTOCOL.concat("://").concat(HOST).concat(BASE_PATH).concat(PATH); } } public List<StudioGhibliFilmDTO> findAllFilms() throws SipadContenziosoInternalException { var response = connector.doGet(BASE_URI, null, null); if (!response.getStatusCode().is2xxSuccessful() || !response.hasBody()) { throw new SipadContenziosoInternalException(Errore.INTERNAL_REST_ERROR, "FindAll(), microservizio ".concat(BASE_URI), null); } return (List<StudioGhibliFilmDTO>) response.getBody(); } }
额外说明
如果此前功能正常,大概率是之前的代码并未使用静态变量存储配置值,而是用实例变量管理。静态变量在Spring环境中通常不建议用于存储依赖注入的配置,除非有特殊需求——优先使用实例变量配合Spring的生命周期管理,能避免这类初始化时机的问题。
内容的提问来源于stack exchange,提问作者Saverio Mirko Viola
相关产品推荐
相关产品推荐

