一个gRPC客户端,其通道的名称取自存根类的名称

后端开发 2026-07-11

Spring-Grpc 中,我可以把声明为bean的客户端配置为使用命名通道:

@Bean
MyServiceGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
    return MyServiceGrpc.newBlockingStub(channels.createChannel("my-service"));
}

@Bean
AnotherServiceGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
    return AnotherServiceGrpc.newBlockingStub(channels.createChannel("another-service"));
}

然后在我的应用程序属性中配置这些通道。例如:

spring.grpc.client.channels.my-service.address=0.0.0.0:9090
spring.grpc.client.channels.another-service.address=0.0.0.0:9091

或者,我也可以通过注解来创建它们:

@ImportGrpcClients(target = "my-service", types = MyServiceGrpc.SimpleBlockingStub.class)
@ImportGrpcClients(target = "another-service", types = AnotherServiceGrpc.SimpleBlockingStub.class)

我希望只使用这个注解并结合包扫描,而不是逐一列出所有客户端,并根据服务的名称来推断通道的名称。

@ImportGrpcClients(basePackages = "mycompany.clients.com")

这是否可能?

解决方案

我通过扩展GrpcClientFactory并注册以替换默认实现来实现了这一点。我本来希望有更简单的方式来做这件事,但正如Max在 他的回答 中所说的那样,看来这是一个刻意的设计决策,不让它变得容易。无论如何,这是我的解决方案:

public class MyGrpcClientFactory extends GrpcClientFactory {

    @Override
    public <S> S getClient(String target, Class<S> type, Class<?> factory) {
        if ("default".equals(target)) {
            target = getChannelName(type);
        }

        return super.getClient(target, type, factory);
    }

    private static String getChannelName(Class<?> type) {
        String name = type.getEnclosingClass().getSimpleName();
        name = name.substring(0, name.indexOf("Grpc"));
        // Change to kebab-case.
        return String.join("-", StringUtils.splitByCharacterTypeCamelCase(name)).toLowerCase();
    }

    /**
     * Registers the AssetTestGrpcClientFactory so that it replaces the standard GrpcClientFactory.
     */
    public static class Registrar implements BeanRegistrar {

        @Override
        public void register(BeanRegistry registry, Environment env) {
            registry.registerBean(
                    GrpcClientFactory.class.getName(), MyGrpcClientFactory.class, BeanRegistry.Spec::primary);
        }
    }
}

然后你需要把Registrar导入到你的 @Configuration 类中:

@Import(MyGrpcClientFactory.Registrar.class)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章