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.
这是我在配置 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.