我希望能够对在我们的AWS后端中创建的所有服务客户端强制执行不同的httpClient
设置和credentialsProvider
。为此,我想使用Java泛型。
无论何时有人创建新的服务客户端,我都想这样使用它:
S3Client s3client = setupAwsClient(S3Client.builder())
.region(Region.EU_WEST_1)
.build();
我的setupAwsClient
的NOT编译提示看起来像这样:
public <T extends AwsSyncClientBuilder<SdkSyncClientBuilder<...>, SdkClient> & BaseClientBuilder<S3ClientBuilder, SdkClient> T setupAwsClient(T client) {
return client
.credentialsProvider(credentialsProvider)
.httpClient(awsBaseClient);
}
问题在于我必须指定太多的接口,以使函数看起来一团糟。
我的问题是:在AWS开发工具包中的所有服务客户端之间执行某种设置的干净方法是什么?泛型是好的解决方案还是有更好的方法?
更新:public <T extends AwsSyncClientBuilder<?,?> & AwsClientBuilder<?, ?>> T setup(T clientBuilder) {
}
尝试此操作也不起作用。甚至AwsClientBuilder
提供credentialsProvider
,而AwsSyncClientBuilder
提供httpClient
。
答案 0 :(得分:0)
AwsSyncClientBuilder将其自身或任何子类型视为类型参数,但是SdkSyncClientBuilder不是AwsSyncClientBuilder的子类型
答案 1 :(得分:0)
您正在寻找的是这种东西吗?
public <T extends AwsSyncClientBuilder<?, ?>> T setup(T clientBuilder) {
/* Do stuff to client */
return clientBuilder;
}
或者如果您想让设置方法调用build:
public <C, T extends AwsSyncClientBuilder<?, C>> C setup(T clientBuilder) {
/* Do stuff to client */
return clientBuilder.build();
}
答案 2 :(得分:0)
我认为您对此考虑过多,让AWS开发工具包的复杂性过滤到您的应用程序代码中。
首先,您是否真的需要异步客户端?与将同步客户端和线程池组合在一起,它们将为您提供什么好处?
第二,您真正要配置什么?看起来您想让调用代码配置区域,而不是凭据提供者?您还有什么要允许或控制的吗?
我将使用的解决方案是一个简单的工厂方法,该方法采用您定义的配置对象:
public static <T> T createClient(Class<T> clientKlass, MyConfigObject config)
因此,根据您的示例,您可能会这样称呼:
MyConfigObject config = new MyConfigObject().withRegion(Region.EU_WEST_1)
S3Client s3Client = createClient(S3Client.class, config)
在createClient()
方法中,我可能会使用一个简单的if-else链来选择合适的构建器:
if (clientKlass == S3Client.class) {
S3ClientBuilder builder = S3Client.builder();
applyConfig(builder, config);
return builder.build();
}
如果您不喜欢if-else链,则可以使用反射在传递的客户端类上调用builder()
方法(在结果上使用build()
方法)。
applyConfig()
方法依赖于从AwsClientBuilder
派生的所有客户端,该客户端提供了用于公共配置的方法:
private static void applyConfig(AwsClientBuilder builder, MyConfiguration config) {
if (config.getRegion() != null) {
builder.region(config.getRegion());
}
builder.credentialsProvider(standardCredentials);
}