标记@Component的类中@Autowired与@Value注入失效问题排查
问题
我尝试了多种方案在类中使用@Value,甚至给构造函数添加了@Autowired,但@Value注解的字段仍为null。我理解这些字段在对象构造后注入,但即便使用普通字符串而非配置属性,值依然是null。
我哪里出错了?我使用的是Spring Boot 3,且Controller中该用法正常,问题应该出在我这边……
相关代码如下:
TokenReceiver类:
@Slf4j @Component public class TokenReceiver { @Value("openid") private String scope; @Value("${spring.security.oauth2.client.registration.keycloak.client-id}") private String clientId; @Value("${spring.security.oauth2.client.registration.keycloak.client-secret}") private String clientSecret; private String grantType = "password"; @Autowired private RestTemplate restTemplate; public String getAccesToken(String username, String password) { String accessTokenUrl = "https://keycloak.fh-kufstein.ac.at:8443/realms/BigOpenRealm/protocol/openid-connect/token"; LinkedMultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>(); requestParams.add("scope", scope); requestParams.add("grant_type", grantType); requestParams.add("client_id", clientId); requestParams.add("client_secret", clientSecret); requestParams.add("username", username); requestParams.add("password", password); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestParams, headers); KeycloakToken keycloakAccessToken = getAccessTokenResponse(request, accessTokenUrl); return keycloakAccessToken.getAccess_token(); }
调用TokenReceiver的GetProxyStrategy类:
@Slf4j @Component public class GetProxyStrategy extends AbstractProxyStrategy { @Autowired TokenReceiver tokenReceiver; public GetProxyStrategy() { super(); } public GetProxyStrategy(HttpServletRequest httpServletRequest, HttpHeaders headers, RestTemplate restTemplate) { super(httpServletRequest, headers); } private StatusAwareEntityHolder callWebservice(String serviceUrl, String username, String password) throws IOException, ProxiedWebServiceExecutionException { String accessToken = tokenReceiver.getAccesToken(username, password);
两个类均在包扫描范围内:
@SpringBootApplication(scanBasePackages = {"my.domain.boo.microservice.portal.*"})
分析与解决
你的问题核心出在GetProxyStrategy的实例化或构造函数处理上,具体原因和解决方法如下:
1. 手动实例化GetProxyStrategy,脱离Spring容器管理
如果代码中通过new GetProxyStrategy(httpServletRequest, headers, restTemplate)手动创建实例,这个对象不属于Spring容器管控,其中的@Autowired TokenReceiver不会被自动注入。若此时你手动new了TokenReceiver,Spring完全不会处理它的@Value注解,字段自然为null。
解决方法:
- 始终从Spring容器获取GetProxyStrategy实例,比如通过@Autowired注入到调用方类中;
- 若需要HttpServletRequest、HttpHeaders这类请求级参数,不要通过构造函数传入,改为在方法内部通过
RequestContextHolder获取,或直接作为方法参数传递给callWebservice。
2. Spring构造函数选择逻辑异常
GetProxyStrategy存在两个构造函数,Spring Boot 3中,多构造函数的@Component类需要显式给要使用的构造函数添加@Autowired,否则Spring可能选择错误的构造函数创建Bean。如果Spring使用了带参数的构造函数,但该构造函数未关联TokenReceiver的注入逻辑,会导致后续字段注入失效。
解决方法:
- 若需要使用带参数的构造函数,给它添加@Autowired注解,并确保构造函数内的参数(HttpServletRequest、RestTemplate等)能被Spring容器提供:
@Autowired public GetProxyStrategy(HttpServletRequest httpServletRequest, HttpHeaders headers, RestTemplate restTemplate) { super(httpServletRequest, headers); }
- 若不需要带参数的构造函数,直接删除它,避免Spring混淆构造函数选择逻辑。
3. 额外验证点
- 确认RestTemplate已通过@Bean注解配置到Spring容器中,否则TokenReceiver的@Autowired RestTemplate会导致Bean初始化失败,间接影响@Value字段注入;
- 验证配置文件中
spring.security.oauth2.client.registration.keycloak.client-id和client-secret的配置有效性(不过你提到硬编码的@Value("openid")也为null,这条优先级较低)。
内容的提问来源于stack exchange,提问作者Octavia
相关产品推荐
相关产品推荐

