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

DAProvider类中TrialHolder注入为空引发NullPointerException问题求助

问题:DAProvider注入TrialHolder为空触发NPE,直接注入其他类正常
  • DAProvider类中TrialHolder对象始终为空,导致NullPointerException(NPE)
  • 直接将TrialHolder注入其他类(如gRPC拦截器)时可正常工作,仅通过DAProvider注入时出现空对象问题

相关代码

gRPC拦截器配置类

import com.role.server.grpc.TrialInterceptorInterceptor;
import com.servicelibs.grpc.Grpc;
import io.grpc.Server;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GrpcConfig {
  @Bean(initMethod = "start", destroyMethod = "shutdown")
  public Server grpcServer(
      Grpc grpc,
          TrialInterceptorInterceptor trialInterceptor)
      throws NoSuchFieldException, IllegalAccessException {
    Server server =
        grpc.newServerBuilder()
            .addService(testConfigServiceGrpc)
            .withInterceptors(
                trialInterceptor)
            .build();

    // 其他逻辑已实现

    return server;
  }
}

gRPC拦截器类

package com.role.server.grpc;

import com.role.server.grpc.ms.grpc.TrialHolder;
import com.spiffe.sc;
import com.spiffe.sp;
import com.libs.oc.xfcc.XForwardedClientCert;
import com.libs.oc.xfcc.XForwardedClientCertList;
import io.grpc.*;
import io.grpc.ServerCall;
import io.grpc.ServerInterceptor;
import java.util.Objects;
import java.util.Optional;
import lombok.Getter;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TrialInterceptor implements ServerInterceptor {
  @Autowired TrialHolder trialHolder;
  private static final Metadata.Key<String> HK =
      Metadata.Key.of("x-forwarded-client-cert", Metadata.ASCII_STRING_MARSHALLER);

  /**
   * 拦截gRPC调用并注入上下文
   */
  @Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> serverCall,
      Metadata metadata,
      ServerCallHandler<ReqT, RespT> serverCallHandler) {

    Optional<sci> sci = getContextInfoFromClientCert(metadata);
    if (!sci.isEmpty()) {
      trialHolder.setsu(sci.get().getsu());
      trialHolder.setsn(sci.get().getsn());
    } else {
      log.warn("sc为空");
    }

    return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(
        serverCallHandler.startCall(serverCall, metadata)) {

      @Override
      public void onComplete() {
        super.onComplete();
      }
    };
  }


  private Optional<sci> getContextInfoFromClientCert(Metadata metadata) {
    String xH = metadata.get(HK);
    XForwardedClientCertList clientCerts = XForwardedClientCertList.fromString(xH);
   if (clientCerts.size() > 1) {
      return clientCerts.stream()
          .map(this::buildsci)
          .filter(Objects::nonNull)
          .findFirst();
    } else {
      return Optional.empty();
    }
  }

  private sci buildsci(
      XForwardedClientCert xforwardedClientCert) {
   // 处理逻辑已实现
    return new sci(
        sc.get().getService().get(), xforwardedClientCert.getSanUri());
  }
}

TrialHolder类

package com.role.server.grpc.service.grpc;

import com.libs.opencontext.api.Key;
import com.libs.opencontext.impl.ocProvider;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TrialHolder {

  private final ocProvider socProvider;

  @Autowired
  public TrialHolder(ocProvider socProvider) {
    this.socProvider = socProvider;
  }

  private void addToContext(Key<String> key, String value) {
    if (socProvider.isPresent() && !StringUtils.isBlank(value)) {
      socProvider.currentContext().put(key, value);
    } 
  }

  <T> Optional<T> getFromContext(Key<T> key) {
    if (socProvider.isPresent()) {
      return Optional.ofNullable(socProvider.currentContext().get(key));
    } else {
      return Optional.empty();
    }
  }

// 以下方法逻辑已实现
  public Optional<String> getsu() {
    return getFromContext("su");
  }

  public void setsu(String su) {
    addToContext("su", su);
  }

  public void setsn(String falconTeam) {
    addToContext("sn", falconTeam);
  }

  public Optional<String> getsn() {
    return getFromContext("sn");
  }

  public boolean isPresent() {
    return socProvider.isPresent();
  }
}

DAProvider类(TrialHolder为空的类)

package com.metadata.da.utils;
import com.role.server.grpc.md.grpc.trialHolder;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class DAProvider {
  private final TrialHolder trialHolder;

  public boolean checkHolder() {
    return trialHolder.getsn().isPresent();
  }
}

DAProvider的使用类

package com.md.dataaccess;


import com.md.da.utils.DAProvider;
import java.util.*;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.spark.sql.types.DataType;
import org.apache.spark.sql.types.DataTypes;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class ConfigProvider {
  private final DAProvider daProvider;

  @Override
  public Config createConfig() {
     return daProvider.checkHolder();
  }
}

报错信息

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dACController': Unsatisfied dependency expressed through field 'configProvider'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ConfigProvider' defined in file ----: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataAccessConfigV1Provider' defined in file -----: Unsatisfied dependency expressed through constructor parameter 8; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'daProvider' defined in file ---: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.role.server.grpc.service.grpc.TrialHolder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: 

解决方案

1. 修正DAProvider中的TrialHolder导入路径

从报错信息和代码对比可以看到,DAProvider中错误导入了路径为com.role.server.grpc.md.grpc.trialHolder的类,而实际TrialHolder的正确包路径是com.role.server.grpc.service.grpc.TrialHolder,且类名首字母需大写。修改DAProvider的import语句:

import com.role.server.grpc.service.grpc.TrialHolder;

2. 验证Spring组件扫描范围

确保Spring的组件扫描覆盖TrialHolder所在的包。如果主启动类的包结构无法自动扫描到com.role.server.grpc.service.grpc,需手动指定扫描路径:

@SpringBootApplication(scanBasePackages = {"com.role.server.grpc", "com.metadata.da", "com.md.dataaccess"})
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

3. 检查TrialHolder的依赖初始化

TrialHolder依赖ocProvider,需确保该类已被Spring识别为bean(添加了@Component注解或通过@Bean配置),否则TrialHolder的bean无法正常创建。


内容的提问来源于stack exchange,提问作者dojacat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 01:09:57