AWS SDK for Java v2 开发规范:优先使用静态工厂方法而非构造器(Favor Static Factory Methods) AWS SDK for Java v2 开发规范优先使用静态工厂方法而非构造器Favor Static Factory Methods【免费下载链接】aws-sdk-java-v2The official AWS SDK for Java - Version 2项目地址: https://gitcode.com/GitHub_Trending/aw/aws-sdk-java-v2静态工厂方法Static Factory Method是 AWS SDK for Java v2 中初始化类实例的核心约定本指南基于 docs/guidelines/FavorStaticFactoryMethods.md 展开并深入结合仓库源码进行验证与扩充。阅读本文后你将掌握 SDK 中create()、builder()、defaultXXX()等工厂方法的命名约定、设计动机与底层实现原理能够在自己的服务客户端、凭据提供者与配置类设计中正确套用这一模式。该规范属于 AWS SDK for Java v2 Development Guidelines 指南系列之一Status: Accepted与 ClientConfiguration.md配置对象不可变性与 Builder 接口、NamingConventions.md 共同构成了 SDK 公共 API 的设计骨架。为什么优先使用静态工厂方法而不是构造器SDK 开发指南开宗明义在一般情况下应优先使用静态工厂方法而非构造器来初始化一个类。这一约定并非凭空规定而是基于以下三点可验证的设计收益。1. 工厂方法名携带语义可读性显著提升构造器与类名相同无法表达这个对象是用什么参数、什么意图创建的。静态工厂方法可以用动词短语直接描述返回对象的语义。指南中的对比示例// 使用静态工厂方法一眼看出正在创建一个使用默认设置的 foobar provider FoobarProvider defaultProvider FoobarProvider.defaultFoobarProvider(); // 使用构造器看不出任何默认行为信息 FoobarProvider defaultProvider new FoobarProvider();从源码结构看这一理念在 SDK 中贯彻到了几乎所有公共入口类上。例如默认凭据提供者 DefaultCredentialsProvider.java 提供builder()作为唯一公开的实例化入口而create()则明确表达返回默认配置的单例这一语义。2. 配合不可变类实现实例复用静态工厂方法非常适合不可变类既然对象一旦创建就不会改变就可以缓存并复用同一个实例避免每次调用都新建对象。SDK 中最典型的例子就是单例缓存// DefaultCredentialsProvider 中缓存的默认单例 private static final DefaultCredentialsProvider DEFAULT_CREDENTIALS_PROVIDER new DefaultCredentialsProvider(builder()); public static DefaultCredentialsProvider create() { return DEFAULT_CREDENTIALS_PROVIDER; }对应源码见 DefaultCredentialsProvider.javaDEFAULT_CREDENTIALS_PROVIDER在类加载时被构造一次之后每次调用create()都返回同一个实例避免了重复构建凭据链的开销。3. 工厂方法可以返回任意子类型解放实现灵活性静态工厂方法声明的返回类型可以是接口或父类而方法内部可以返回任何满足要求的子类型。这意味着 SDK 可以在不破坏 API 的前提下将实现类隐藏在包内部或按需切换不同实现。BackoffStrategy是这一点的绝佳证据。SDK 同时存在两代实现老一代接口 core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/backoff/BackoffStrategy.java 的defaultStrategy()根据当前RetryModeLEGACY / STANDARD / ADAPTIVE返回不同的FullJitterBackoffStrategy或EqualJitterBackoffStrategy实例新一代接口 core/retries-spi/src/main/java/software/amazon/awssdk/retries/api/BackoffStrategy.java 更是把工厂方法直接定义在接口上retryImmediately()、fixedDelay(Duration)、fixedDelayWithoutJitter(...)、exponentialDelay(...)、exponentialDelayHalfJitter(...)、exponentialDelayWithoutJitter(...)分别返回Immediately、FixedDelayWithJitter、ExponentialDelayWithJitter等隐藏在internal包下的实现类。调用方只面对BackoffStrategy接口完全不感知具体实现类这正是返回任意子类型带来的 API 稳定性红利。静态工厂方法的两点代价与规避方式指南也坦诚列出了静态工厂方法相对构造器的缺点并给出了可落地的解决方案可发现性不如构造器用户习惯了new可能不清楚该类提供了哪些工厂方法。规避手段有两条其一SDK 统一约定一组常见方法名如create()让用户在多个类间迁移时零学习成本其二依赖 IntelliJ、Eclipse 等智能 IDE 的自动补全与提示能力。无法被继承没有 public/protected 构造器的类不能被子类化。但这并非缺陷——它反向推动开发者优先使用组合composition而非继承inheritance。SDK 中大量final类如DefaultCredentialsProvider本身就是public final class正是这一权衡的体现通过 Builder 和组合链来扩展行为而不是靠继承。完整示例剖析DefaultCredentialsProvider 的工厂方法设计指南给出了 SDK 中DefaultCredentialsProvider的简化示例仓库中 DefaultCredentialsProvider.java 的完整实现可拆解为以下四个要素SdkPublicApi public final class DefaultCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable, ToCopyableBuilderDefaultCredentialsProvider.Builder, DefaultCredentialsProvider { // 要素一类加载期构建的默认单例 private static final DefaultCredentialsProvider DEFAULT_CREDENTIALS_PROVIDER new DefaultCredentialsProvider(builder()); // 要素二构造器是私有的外部无法直接 new private DefaultCredentialsProvider(Builder builder) { this.providerChain createChain(builder); } // 要素三create() 返回默认配置单例当前已标记 Deprecated见下文 Deprecated public static DefaultCredentialsProvider create() { return DEFAULT_CREDENTIALS_PROVIDER; } // 要素四builder() 返回可配置的 Builder public static Builder builder() { return new Builder(); } // Builder 必须是 public static final 的嵌套类 public static final class Builder implements CopyableBuilderBuilder, DefaultCredentialsProvider { // profileFile / profileName / reuseLastProviderEnabled / asyncCredentialUpdateEnabled 等配置项 // ... } }四种创建实例的方式对比如下// 方式一使用默认配置的单例create 返回缓存实例 DefaultCredentialsProvider defaultCredentialsProvider1 DefaultCredentialsProvider.create(); // 方式二通过 Builder 自定义配置后构建推荐 DefaultCredentialsProvider defaultCredentialsProvider2 DefaultCredentialsProvider.builder().build();需要特别指出的一个演进细节create()目前在源码中已被标记Deprecated见 DefaultCredentialsProvider.java其 Javadoc 明确说明——返回单例的方式可能在某个客户端close()掉该 provider 时影响其他仍在使用的客户端因此官方推荐改用builder().build()创建相互独立的实例。这恰好印证了指南中工厂方法配合不可变对象复用的收益与边界单例复用省资源但共享可变生命周期时需谨慎。Builder 中四个可配置字段及其默认值来自 DefaultCredentialsProvider.java配置项默认值说明profileFile默认位置~/.aws/credentials自定义凭据配置文件可传ProfileFile或SupplierProfileFileprofileName默认 profile指定使用的 profile 名称reuseLastProviderEnabledtrue是否复用凭据链中上一次成功的 provider开启后解析凭据更快asyncCredentialUpdateEnabledfalse是否后台异步刷新凭据开启后resolveCredentials()更少阻塞但占用额外资源底层createChain(builder)DefaultCredentialsProvider.java用工厂方法串联了六层凭据来源SystemPropertyCredentialsProvider.create()→EnvironmentVariableCredentialsProvider.create()→WebIdentityTokenFileCredentialsProvider.builder().build()→ProfileCredentialsProvider.builder().build()→ContainerCredentialsProvider.builder().build()→InstanceProfileCredentialsProvider.builder().build()。可以看到链上的每个 provider 同样遵循静态工厂方法约定形成了 SDK 内部自洽的一致风格。静态工厂方法的命名约定指南将工厂方法名收敛为两类避免各模块命名发散create()/create(params)—— 创建新实例用于无歧义地创建并返回一个新实例。示例DynamoDBClient.create()、DynamoDBClient.builder().build()。SDK 中所有服务客户端DynamoDB、S3、SQS 等均由代码生成器统一生成这一对入口保证跨服务 API 形状一致。这一约定在代码生成器中有直接证据codegen 模块的 BaseClientBuilderClass.java 与 SyncClientClass.java 中大量通过$T.create()形式的 JavaPoet 代码块注入工厂调用如默认 token provider、默认认证方案 provider、RequestChecksumCalculationResolver.create()等说明**create()是代码生成器层面的硬编码规范**而不仅是手工代码的习惯。defaultXXX()—— 返回默认配置实例用于返回使用默认设置的单例或实例。示例BackoffStrategy.defaultStrategy()、BackoffStrategy.defaultThrottlingStrategy()。以 core/sdk-core/src/main/java/software/amazon/awssdk/core/retry/backoff/BackoffStrategy.java 为例defaultStrategy()是无参重载内部委托给按RetryMode分发的defaultStrategy(RetryMode)构造FullJitterBackoffStrategy并填入来自SdkDefaultRetrySetting的默认 base delay 与MAX_BACKOFF上限。在测试代码 RetryPolicyTest.java 中RetryPolicy默认行为被断言为BackoffStrategy.defaultStrategy()证明该工厂方法确实是运行时默认值的事实来源Ec2MetadataRetryPolicyTest.java 亦用同样的方式获取默认退避策略。在实际编码中如何落地这套约定结合指南与源码可以在自己编写的 SDK 扩展或服务代码中按以下清单应用类设计层面优先把类声明为final构造器设为private或package-private通过组合扩展行为对外只暴露public static工厂方法。默认实例若类有零配置即可用的语义提供public static Xxx defaultXxx()并在内部用private static final字段缓存单例前提是实例不可变且无共享生命周期风险。可配置实例提供public static Builder builder()Builder 作为public static final嵌套类实现build()返回新实例需要深拷贝时可实现ToCopyableBuilder/CopyableBuilder见 DefaultCredentialsProvider.java 的toBuilder()。命名纪律创建新实例用create()/create(params)返回默认配置实例用defaultXXX()不要自创getInstance()、newInstance()等变体保持与 SDK 全库风格统一。单例与生命周期权衡当单例实例拥有可关闭的资源如凭据 provider 实现SdkAutoCloseable时要评估共享关闭带来的影响必要时推荐用户通过builder().build()获取独立实例——这正是DefaultCredentialsProvider.create()被弃用的原因。总结Favor Static Factory Methods是 AWS SDK for Java v2 公共 API 设计中最基础的约定之一它以有语义的方法名、不可变对象的实例复用、返回子类型的实现灵活性三项收益换取了两点可控的代价可发现性与不可继承性并通过统一的create()/defaultXXX()命名让整套 SDK 的用户心智保持一致。从DefaultCredentialsProvider的私构造器 单例缓存 Builder 四要素到BackoffStrategy接口上的静态工厂家族再到 codegen 生成器中硬编码的$T.create()调用仓库源码处处印证着这一规范的落地深度。理解并遵循这一约定是读懂 SDK 公共 API、编写风格一致的扩展代码的前提。【免费下载链接】aws-sdk-java-v2The official AWS SDK for Java - Version 2项目地址: https://gitcode.com/GitHub_Trending/aw/aws-sdk-java-v2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考