1

我对弹簧/弹簧靴比较陌生。

目前我正在使用一个 Spring Boot Rest 应用程序,它提供了一个 FeignClient 以包含在其他项目中。现在,我希望那些 FeignClients 被 CircuitBreaker 包裹起来。

我想出的最佳解决方案是动态创建一个代理,其中包括 CircuitBreaker 实现,它本身调用创建的 FeignClient。

因此,假设我有以下描述 RestController 的接口:

@RequestMapping("/")
public interface MyWebService {

    @GetMapping("name")
    public String getName();
}

现在,我有了 FeignClient 的接口:

@FeignClient("app")
public interface WebServiceClient extends WebService {
}

所以.. 我的目标是实现类似我有另一个注释的东西,例如@WithCircuitBreaker,然后我将被扫描并动态创建一个代理 bean,它将被注入而不是 FeignClient bean。

目前我的代码如下所示:

@FeignClient("app")
@WithCircuitBreaker
public interface WebServiceClient extends WebService {
}

据我所知,我现在可以创建一个@Configuration如下所示的类:

@Configuration
public class WithCircuitBreakerConfiguration implements ImportAware {

    private AnnotationMetadata annotationMetadata;
    private AnnotationAttributes annotationAttributes;

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        this.annotationMetadata = importMetadata;
        Map<String, Object> annotatedClasses = importMetadata.getAnnotationAttributes(WithCircuitBreaker.class.getName());
        this.annotationAttributes = AnnotationAttributes.fromMap(annotatedClasses);
    }

    What else to import to create the proxy and inject it?
}

现在我到了这一点,我不知道如何继续。如何动态创建执行以下操作的代理类:

public class PorxyedWebService {

    private WebService feignClientProxy;

    @Autowired
    public ProxyedWebService(WebService feignClientProxy) {
        this.feignClientProxy = feignClientProxy;
    }

    public String getName() {
        ...
        <some circuitbreaker stuff>
        ....
        return this.feignClientProxy.getName();
    }
}

然后一旦有人自动WebService连接接口,就返回这个代理而不是从 Feign 生成的代理。

4

2 回答 2

0

我不是 Spring 用户,但我知道 Spring 不会递归地创建代理,例如,如果多个 Spring AOP 方面应用于同一个对象。相反,在同一个代理上注册了额外的拦截器(或 AOP 语言中的通知)。我认为您想使用该基础架构来实现您的目标。

于 2019-09-20T04:16:19.997 回答
0

您可以只使用弹性 4j Spring Boot2 启动器。您可以将@CircuitBreaker注释与@FeignClient接口级别的注释结合起来。

然后,您可以按如下方式使用它:

@FeignClient(name = DUMMY_FEIGN_CLIENT_NAME)
@CircuitBreaker(name = DUMMY_FEIGN_CLIENT_NAME)
public interface DummyFeignClient {

    String DUMMY_FEIGN_CLIENT_NAME = "dummyFeignClient";

    @GetMapping(path = "/api/{param}")
    void doSomething(@PathVariable(name = "param") String param);
} 

于 2019-09-25T12:06:03.563 回答