You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

标记@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:55:19