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
相关产品推荐
相关产品推荐

