Spring: 重新初始化了一个bean

Spring: re-initialized a bean

这是我在配置 class 中创建 gRPC ManagedChannel 的 Spring bean:

@Configuration
public class CockroachDbConfig {


 @Bean
 public ManagedChannel getManagedChannel() {
    return ManagedChannelBuilder.forTarget(CR_GRPC_SERVER)
        .usePlaintext()
        .build();
   }
 }

控制器方法如下:

@RestController
public class DBProxyController {

    @Autowired
    private DBProxyService dbProxyService;


    @RequestMapping(value = "/", method = RequestMethod.POST,
        consumes = APPLICATION_JSON_VALUE,
        produces = APPLICATION_JSON_VALUE
    )
    @SuppressWarnings("BlockingMethodInNonBlockingContext")
    public Mono<Void> handleRequest(@RequestBody String requestBody, ServerHttpResponse serverHttpResponse, ServerHttpRequest request)  {


        org.springframework.http.HttpHeaders headers = request.getHeaders();

        Map<String, String> responseMap = dbProxyService.processRequest(requestBody, headers);

        String response = responseMap.get(X_AMZN_RESPONSE);

        if (response.equalsIgnoreCase("{}")) {
            LOGGER.info("We are ot able to sucessfully process the request and reutning an empty response");
        }

        return serverHttpResponse.writeWith(strToDataBuffer(response));
    }
}

服务class是:

@Service
public class DBProxyService {


    public Map<String, String> processRequest(final String requestBody, final org.springframework.http.HttpHeaders headers)  {


        ManagedChannel customManagedChannel = (new CockroachDbConfig()).getManagedChannel();

        switch (action) {

            case GETITEM:
            {

                // some code
                ProtoService.shutdownManagedChannel(customManagedChannel);
            }
            case PUTITEM:
            {
                // some code
                ProtoService.shutdownManagedChannel(customManagedChannel);
            }
            
        }

    }

}

对于每个请求,我在服务方法 processRequest 中创建一个新的 ManagedChannel 并使用名为 shutdownManagedChannel 的方法将其关闭。

早些时候,我尝试使用 @Autowired 作为托管频道,如下所示:

@Service
public class DBProxyService {


    @Autowired 
    private ManagedChannel customManagedChannel;

    public Map<String, String> processRequest(final String requestBody, final org.springframework.http.HttpHeaders headers)  {



        switch (action) {

            case GETITEM:
            {

                // some code
                ProtoService.shutdownManagedChannel(customManagedChannel);
            }
            case PUTITEM:
            {
                // some code
                ProtoService.shutdownManagedChannel(customManagedChannel);
            }
            
        }

    }

}

这没有成功,因为我在每个请求完成后关闭了通道,我想我需要想办法为每个调用重新初始化 bean。

那么,当应用程序 运行 时,如何为每个请求重新初始化 ManagedChannel

谢谢。

一个不太依赖框架的简单解决方案是注入类型为 Supplier<ManagedChannel> 的 bean(或适用于您的用例的任何其他功能接口类型)。

@Bean
public Suuplier<ManagedChannel> getManagedChannel() {
  return () -> ManagedChannelBuilder.forTarget(CR_GRPC_SERVER)
      .usePlaintext()
      .build();
}

然后在需要时使用get方法re-instantiate一个新频道。

否则,您可以使用在某些情况下重新创建 bean 的范围 Prototype,而不是将其视为单例 (documentation). Be aware that injecting prototype beans in singleton beans require you to do some configuration gymnastic, as stated in the point 1.5.3 of the documentation.