

これは AWS CDK v2 デベロッパーガイドです。旧版の CDK v1 は 2022 年 6 月 1 日にメンテナンスを開始し、2023 年 6 月 1 日にサポートを終了しました。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# AWS CDK コンストラクト
<a name="constructs"></a>

コンストラクトは、 AWS Cloud Development Kit (AWS CDK) アプリケーションの基本的な構成要素です。コンストラクトは、1 つ以上の AWS CloudFormation リソースとその設定を表すアプリケーション内のコンポーネントです。コンストラクトをインポートして設定することで、アプリケーションを 1 つずつ構築していきます。

## コンストラクトをインポートして使用する
<a name="constructs-import"></a>

コンストラクトは、[AWS コンストラクトライブラリ](libraries.md#libraries-construct) から CDK アプリケーションにインポートするクラスです。また、独自のコンストラクトを作成および配布することや、サードパーティーの開発者によって作成されたコンストラクトを使用することもできます。

コンストラクトは、コンストラクトプログラミングモデル (CPM) の一部です。CDK for Terraform (CDKtf)、CDK for Kubernetes (CDK8s)、Projen など、他のツールでも使用できます。

多数のサードパーティーも AWS CDK と互換性のあるコンストラクトを公開しています。 AWS CDK [コンストラクトパートナーエコシステムについては、Construct Hub](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&offset=0) を参照してください。

## コンストラクトレベル
<a name="constructs-lib-levels"></a>

コンストラクトライブラリからの AWS コンストラクトは、3 つのレベルに分類されます。各レベルは、抽象化のレベルが段階的に上がっていきます。抽象化が高いほど、設定が容易になり、必要な専門知識も少なくなります。抽象化が低いほど、より高度なカスタマイズが可能になりますが、より多くの専門知識が必要になります。<a name="constructs-lib-levels-one"></a>

 **レベル 1 (L1) コンストラクト**   
L1 コンストラクトは、*CFN リソース* とも呼ばれ、最下位のコンストラクトであり、抽象化は行いません。各 L1 コンストラクトは、単一の AWS CloudFormation リソースに直接マッピングされます。L1 コンストラクトでは、特定の AWS CloudFormation リソースを表すコンストラクトをインポートします。次に、コンストラクトインスタンス内でリソースのプロパティを定義します。  
L1 コンストラクトは、 AWS CloudFormation に精通しており、 AWS リソースプロパティの定義を完全に制御する必要がある場合に最適です。  
コンストラクトライブラリでは、L1 AWS コンストラクトの名前は で始まり`Cfn`、その後にそれが表す AWS CloudFormation リソースの識別子が続きます。たとえば、 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CfnBucket.html)コンストラクトは [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) AWS CloudFormation リソースを表す L1 コンストラクトです。  
L1 コンストラクトは、[AWS CloudFormation リソース仕様](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html)から生成されます。リソースが AWS CloudFormation に存在する場合、L1 コンストラクトとして AWS CDK で使用できます。新しいリソースまたはプロパティが AWS コンストラクトライブラリで使用可能になるまでに最大 1 週間かかる場合があります。詳細については、* AWS 「 CloudFormation ユーザーガイド*」の[AWS 「リソースタイプとプロパティタイプのリファレンス](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)」を参照してください。<a name="constructs-lib-levels-two"></a>

 **レベル 2 (L2) コンストラクト**   
*キュレーションされた*コンストラクトとも呼ばれる L2 コンストラクトは、CDK チームによって慎重に開発され、通常は最も広く使用されているコンストラクトタイプです。L2 コンストラクトは、L1 コンストラクトと同様に single AWS CloudFormation リソースに直接マッピングされます。L1 コンストラクトと比較して、L2 コンストラクトは直感的なインテントベースの API を通してより高度な抽象化を提供します。L2 コンストラクトには、適切なデフォルトプロパティ設定、ベストプラクティスのセキュリティポリシー、および多くのボイラープレートコードやグルーロジックを生成する機能が含まれています。  
L2 コンストラクトは、ほとんどのリソースにヘルパーメソッドも提供します。これにより、プロパティ、アクセス許可、リソース間のイベントベースのインタラクションなどをより簡単かつ迅速に定義できます。これらの機能の多くは、[Mixins](mixins.md) と呼ばれる独立した構成要素としても利用でき、 `.with()`メソッドを使用して L1 コンストラクトと L2 コンストラクトの両方に適用できます。  
[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) クラスは、Amazon Simple Storage Service (Amazon S3) バケットリソースの L2 コンストラクトの一例です。  
 AWS コンストラクトライブラリには、安定して本番環境で使用できるように指定された L2 コンストラクトが含まれています。開発中の L2 コンストラクトは実験的なものとして指定され、別個のモジュールとして提供されます。<a name="constructs-lib-levels-three"></a>

 **レベル 3 (L3) コンストラクト**   
L3 コンストラクトは、*パターン*とも呼ばれ、最も高度な最高レベルです。各 L3 コンストラクトには、アプリケーション内の特定のタスクまたはサービスを達成するために連携するように設定された、複数リソースの集合を含めることができます。L3 コンストラクトは、アプリケーションの特定のユースケースの AWS アーキテクチャ全体を作成するために使用されます。  
完全なシステム設計、または大規模なシステムの主要部分を提供するために、L3 コンストラクトは、独自の考えに基づくデフォルトのプロパティ設定を提供します。これらは、問題を解決し、解決策を提供するための特定のアプローチを軸に構築されています。L3 コンストラクトを使用すると、入力とコードの量を最小限に抑えながら、複数のリソースをすばやく作成して設定できます。  
[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs_patterns.ApplicationLoadBalancedFargateService.html) クラスは、Amazon Elastic Container Service (Amazon ECS) クラスターで実行され、アプリケーションロードバランサーにフロントされる AWS Fargate サービスを表す L3 コンストラクトの例です。  
L2 コンストラクトと同様に、本番環境で使用できる L3 AWS コンストラクトは コンストラクトライブラリに含まれています。開発中のものは、別個のモジュールで提供されます。

## コンストラクトの定義
<a name="constructs-define"></a>

### コンポジション
<a name="constructs-composition"></a>

 *コンポジション*は、コンストラクトを通して高レベルの抽象化を定義するための重要なパターンです。高レベルのコンストラクトは、任意の数の低レベルのコンストラクトから構成できます。ボトムアップの観点からは、 コンストラクトを使用して、デプロイする個々の AWS リソースを整理します。必要な階層数で、目的に応じて便利な抽象化を使用します。

コンポジションを使用することで、再利用可能なコンポーネントを定義し、他のコードと同様に共有することができます。たとえば、チームはバックアップ、グローバルレプリケーション、自動スケーリング、モニタリングなど、Amazon DynamoDB テーブルに対する会社のベストプラクティスを実装するコンストラクトを定義できます。チームは、コンストラクトを内部的に他のチームと共有することも、公開することもできます。

チームは、他のライブラリパッケージと同様にコンストラクトを使用できます。ライブラリが更新されると、開発者は他のコードライブラリと同様に、新しいバージョンの改善やバグ修正にアクセスできるようになります。

### 初期化
<a name="constructs-init"></a>

コンストラクトは、[https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) 基底クラスを拡張したクラスとして実装されます。コンストラクトの定義は、クラスのインスタンス化によって行います。すべてのコンストラクトは、初期化時に以下の 3 つのパラメータを取ります。
+  **scope** – コンストラクトの親または所有者。これはスタックでも別のコンストラクトでもかまいません。スコープは、[コンストラクトツリー](apps.md#apps-tree)内のコンストラクトの場所を決定します。通常は、現在のオブジェクトを表す `this` (Python では `self`) をスコープとして渡すべきです。
+  **id** — スコープ内で一意でなければならない[識別子](identifiers.md)です。識別子は、 コンストラクト内で定義されているすべての名前空間として機能します。これは、[リソース名](resources.md#resources-physical-names)や AWS CloudFormation 論理 IDs などの一意の識別子を生成するために使用されます。

  識別子が一意である必要があるのはスコープ内のみです。これにより、含まれる可能性のあるコンストラクトと識別子を気にせずにコンストラクトをインスタンス化して再利用でき、コンストラクトを組み合わせてより高いレベルの抽象化を作成できるようになります。さらに、スコープを使用すると、コンストラクトのグループを一度に参照できます。例としては、[タグ付け](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Tag.html)や、コンストラクトのデプロイ先の指定などが挙げられます。
+  **props** – 言語に応じて、コンストラクトの初期設定を定義するプロパティまたはキーワード引数のセット。高レベルのコンストラクトであるほど多くのデフォルト値が提供され、すべての prop 要素がオプションである場合は、props パラメータを完全に省略することができます。

### 設定
<a name="constructs-config"></a>

ほとんどのコンストラクトは、3 番目の引数 (Python ではキーワード引数) として `props` を受け入れます。これは、コンストラクトの設定を定義する名前と値のコレクションです。次の例では、 AWS Key Management Service (AWS KMS) 暗号化と静的ウェブサイトホスティングが有効になっているバケットを定義します。暗号化キーの明示的な指定はされていないため、`Bucket` コンストラクトは新しい `kms.Key` を定義してバケットに関連付けます。

**Example**  

```
new s3.Bucket(this, 'MyEncryptedBucket', {
  encryption: s3.BucketEncryption.KMS,
  websiteIndexDocument: 'index.html'
});
```

```
new s3.Bucket(this, 'MyEncryptedBucket', {
  encryption: s3.BucketEncryption.KMS,
  websiteIndexDocument: 'index.html'
});
```

```
s3.Bucket(self, "MyEncryptedBucket", encryption=s3.BucketEncryption.KMS,
    website_index_document="index.html")
```

```
Bucket.Builder.create(this, "MyEncryptedBucket")
        .encryption(BucketEncryption.KMS_MANAGED)
        .websiteIndexDocument("index.html").build();
```

```
new Bucket(this, "MyEncryptedBucket", new BucketProps
{
    Encryption = BucketEncryption.KMS_MANAGED,
    WebsiteIndexDocument = "index.html"
});
```

```
	awss3.NewBucket(stack, jsii.String("MyEncryptedBucket"), &awss3.BucketProps{
		Encryption: awss3.BucketEncryption_KMS,
		WebsiteIndexDocument: jsii.String("index.html"),
	})
```

### コンストラクトの操作
<a name="constructs-interact"></a>

コンストラクトは、基底クラスである [Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) クラスを拡張したクラスです。コンストラクトをインスタンス化すると、コンストラクトオブジェクトは一連のメソッドとプロパティを公開します。これにより、コンストラクトを操作し、システムの他の部分への参照として渡すことができます。

 AWS CDK フレームワークでは、コンストラクトの APIsに制限はありません。作成者は必要な API を定義できます。ただし、 などの AWS コンストラクトライブラリに含まれているコンストラクト AWS は`s3.Bucket`、ガイドラインと一般的なパターンに従います。これにより、すべての AWS リソースで一貫したエクスペリエンスが提供されます。

ほとんどの AWS コンストラクトには、そのコンストラクトに対する AWS Identity and Access Management (IAM) アクセス許可をプリンシパルに付与するために使用できる一連の[付与](permissions.md#permissions-grants)メソッドがあります。以下の例では、IAM グループ `data-science` に対し、Amazon S3 バケット `raw-data` から読み取りを行うためのアクセス許可を付与します。

**Example**  

```
const rawData = new s3.Bucket(this, 'raw-data');
const dataScience = new iam.Group(this, 'data-science');
rawData.grants.read(dataScience);
```

```
const rawData = new s3.Bucket(this, 'raw-data');
const dataScience = new iam.Group(this, 'data-science');
rawData.grants.read(dataScience);
```

```
raw_data = s3.Bucket(self, 'raw-data')
data_science = iam.Group(self, 'data-science')
raw_data.grants.read(data_science)
```

```
Bucket rawData = new Bucket(this, "raw-data");
Group dataScience = new Group(this, "data-science");
rawData.getGrants().read(dataScience);
```

```
var rawData = new Bucket(this, "raw-data");
var dataScience = new Group(this, "data-science");
rawData.Grants.Read(dataScience);
```

```
	rawData := awss3.NewBucket(stack, jsii.String("raw-data"), nil)
	dataScience := awsiam.NewGroup(stack, jsii.String("data-science"), nil)
	rawData.Grants().Read(dataScience, nil)
```

もう 1 つの一般的なパターンは、 AWS コンストラクトが他の場所で提供されたデータからリソースの属性の 1 つを設定することです。属性には、Amazon リソースネーム (ARN)、名前、または URL などが含まれます。

次のコードは、 AWS Lambda 関数を定義し、環境変数のキューの URL を介して Amazon Simple Queue Service (Amazon SQS) キューに関連付けます。

**Example**  

```
const jobsQueue = new sqs.Queue(this, 'jobs');
const createJobLambda = new lambda.Function(this, 'create-job', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('./create-job-lambda-code'),
  environment: {
    QUEUE_URL: jobsQueue.queueUrl
  }
});
```

```
const jobsQueue = new sqs.Queue(this, 'jobs');
const createJobLambda = new lambda.Function(this, 'create-job', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('./create-job-lambda-code'),
  environment: {
    QUEUE_URL: jobsQueue.queueUrl
  }
});
```

```
jobs_queue = sqs.Queue(self, "jobs")
create_job_lambda = lambda_.Function(self, "create-job",
    runtime=lambda_.Runtime.NODEJS_18_X,
    handler="index.handler",
    code=lambda_.Code.from_asset("./create-job-lambda-code"),
    environment=dict(
        QUEUE_URL=jobs_queue.queue_url
    )
)
```

```
final Queue jobsQueue = new Queue(this, "jobs");
Function createJobLambda = Function.Builder.create(this, "create-job")
                .handler("index.handler")
                .code(Code.fromAsset("./create-job-lambda-code"))
                .environment(java.util.Map.of(   // Map.of is Java 9 or later
                    "QUEUE_URL", jobsQueue.getQueueUrl()))
                .build();
```

```
var jobsQueue = new Queue(this, "jobs");
var createJobLambda = new Function(this, "create-job", new FunctionProps
{
    Runtime = Runtime.NODEJS_18_X,
    Handler = "index.handler",
    Code = Code.FromAsset(@".\create-job-lambda-code"),
    Environment = new Dictionary<string, string>
    {
        ["QUEUE_URL"] = jobsQueue.QueueUrl
    }
});
```

```
	createJobLambda := awslambda.NewFunction(stack, jsii.String("create-job"), &awslambda.FunctionProps{
		Runtime: awslambda.Runtime_NODEJS_18_X(),
		Handler: jsii.String("index.handler"),
		Code:    awslambda.Code_FromAsset(jsii.String(".\\create-job-lambda-code"), nil),
		Environment: &map[string]*string{
			"QUEUE_URL": jsii.String(*jobsQueue.QueueUrl()),
		},
	})
```

コンストラクトライブラリの最も一般的な API AWS パターンについては、[「リソース」と AWS 「CDK](resources.md)」を参照してください。

### Mixins で機能を追加する
<a name="constructs-mixins"></a>

ミキサーは、 `.with()`メソッドを使用して任意のコンストラクトに適用できる構成可能な機能です。Mixins を使用すると、別のコンストラクトを使用したり、低レベルコードを記述したりすることなく、L1 および L2 コンストラクトに機能を追加できます。

例えば、L1 `CfnBucket`か L2 かにかかわらず、Amazon S3 バケットでバージョニングを有効にしてパブリックアクセスをブロックできます`Bucket`。

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

// Apply mixins to an L1 construct
new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());

// Apply mixins to an L2 construct
new s3.Bucket(this, 'MyL2Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY })
  .with(new s3.mixins.BucketAutoDeleteObjects());
```

```
const cdk = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

// Apply mixins to an L1 construct
new s3.CfnBucket(this, 'MyBucket')
  .with(new s3.mixins.BucketVersioning())
  .with(new s3.mixins.BucketBlockPublicAccess());

// Apply mixins to an L2 construct
new s3.Bucket(this, 'MyL2Bucket', { removalPolicy: cdk.RemovalPolicy.DESTROY })
  .with(new s3.mixins.BucketAutoDeleteObjects());
```

```
import aws_cdk as cdk
import aws_cdk.aws_s3 as s3

# Apply mixins to an L1 construct
s3.CfnBucket(self, "MyBucket") \
    .with_(s3.mixins.BucketVersioning()) \
    .with_(s3.mixins.BucketBlockPublicAccess())

# Apply mixins to an L2 construct
s3.Bucket(self, "MyL2Bucket", removal_policy=cdk.RemovalPolicy.DESTROY) \
    .with_(s3.mixins.BucketAutoDeleteObjects())
```

```
import software.amazon.awscdk.*;
import software.amazon.awscdk.services.s3.*;

// Apply mixins to an L1 construct
CfnBucket bucket = new CfnBucket(this, "MyBucket");
bucket.with(new BucketVersioning());
bucket.with(new BucketBlockPublicAccess());

// Apply mixins to an L2 construct
Bucket l2Bucket = Bucket.Builder.create(this, "MyL2Bucket")
        .removalPolicy(RemovalPolicy.DESTROY)
        .build();
l2Bucket.with(new BucketAutoDeleteObjects());
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

// Apply mixins to an L1 construct
var bucket = new CfnBucket(this, "MyBucket");
bucket.With(new BucketVersioning());
bucket.With(new BucketBlockPublicAccess());

// Apply mixins to an L2 construct
var l2Bucket = new Bucket(this, "MyL2Bucket", new BucketProps
{
    RemovalPolicy = RemovalPolicy.DESTROY
});
l2Bucket.With(new BucketAutoDeleteObjects());
```

```
bucket := awss3.NewCfnBucket(stack, jsii.String("MyBucket"), nil)
bucket.With(awss3.NewBucketVersioning())
bucket.With(awss3.NewBucketBlockPublicAccess())

l2Bucket := awss3.NewBucket(stack, jsii.String("MyL2Bucket"), &awss3.BucketProps{
    RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
})
l2Bucket.With(awss3.NewBucketAutoDeleteObjects())
```

ミキサーは、各サービスモジュール`mixins`の名前空間 ( など`s3.mixins`) から使用できます。各ミックスインは特定のリソースタイプをターゲットとし、そのリソースにちなんで命名されます。ミックスインを L2 コンストラクトに適用すると、そのミックスは基盤となる L1 リソースに自動的に適用されます。

Mixins の詳細については、[「Mixins](mixins.md)」を参照してください。

### アプリケーションとスタックのコンストラクト
<a name="constructs-apps-stacks"></a>

 AWS コンストラクトライブラリの [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.App.html)および [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Stack.html) クラスは一意のコンストラクトです。他のコンストラクトと比較して、リソース AWS は独自に設定されません。代わりに、他のコンストラクトにコンテキストを提供するために使用されます。 AWS リソースを表すすべてのコンストラクトは、`Stack`コンストラクトの範囲内で直接または間接的に定義する必要があります。 `Stack`コンストラクトは、`App`コンストラクトの範囲内で定義されます。

CDK アプリの詳細については、「[AWS CDK アプリ](apps.md)」を参照してください。CDK スタックの詳細については、[AWS 「CDK スタックの概要](stacks.md)」を参照してください。

以下の例では、単一のスタックを持つアプリケーションを定義します。スタック内では、L2 コンストラクトを使用して Amazon S3 バケットリソースを設定します。

**Example**  

```
import { App, Stack, StackProps } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

class HelloCdkStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

const app = new App();
new HelloCdkStack(app, "HelloCdkStack");
```

```
const { App , Stack } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');

class HelloCdkStack extends Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyFirstBucket', {
      versioned: true
    });
  }
}

const app = new App();
new HelloCdkStack(app, "HelloCdkStack");
```

```
from aws_cdk import App, Stack
import aws_cdk.aws_s3 as s3
from constructs import Construct

class HelloCdkStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        s3.Bucket(self, "MyFirstBucket", versioned=True)

app = App()
HelloCdkStack(app, "HelloCdkStack")
```
`HelloCdkStack.java` ファイルで定義されるスタック:  

```
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.*;

public class HelloCdkStack extends Stack {
    public HelloCdkStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public HelloCdkStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Bucket.Builder.create(this, "MyFirstBucket")
            .versioned(true).build();
    }
}
```
`HelloCdkApp.java` ファイルで定義されるアプリケーション:  

```
import software.amazon.awscdk.App;
import software.amazon.awscdk.StackProps;

public class HelloCdkApp {
    public static void main(final String[] args) {
        App app = new App();

        new HelloCdkStack(app, "HelloCdkStack", StackProps.builder()
                .build());

        app.synth();
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.S3;

namespace HelloCdkApp
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            var app = new App();
            new HelloCdkStack(app, "HelloCdkStack");
            app.Synth();
        }
    }

    public class HelloCdkStack : Stack
    {
        public HelloCdkStack(Construct scope, string id, IStackProps props=null) : base(scope, id, props)
        {
            new Bucket(this, "MyFirstBucket", new BucketProps { Versioned = true });
        }
    }
}
```

```
func NewHelloCdkStack(scope constructs.Construct, id string, props *HelloCdkStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{
		Versioned: jsii.Bool(true),
	})

	return stack
}
```

## コンストラクトの使用
<a name="constructs-work"></a>

### L1 コンストラクトの使用
<a name="constructs-l1-using"></a>

L1 コンストラクトは、個々の AWS CloudFormation リソースに直接マッピングされます。設定に必要なリソースは自分で用意しなければなりません。

この例では、L1 `CfnBucket` コンストラクトを使用して `bucket` オブジェクトを作成します。

**Example**  

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket"
});
```

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket"
});
```

```
bucket = s3.CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket")
```

```
CfnBucket bucket = new CfnBucket.Builder().bucketName("amzn-s3-demo-bucket").build();
```

```
var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps
{
    BucketName= "amzn-s3-demo-bucket"
});
```

```
	awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{
		BucketName: jsii.String("amzn-s3-demo-bucket"),
	})
```

単純なブール語、文字列、数値、コンテナではないコンストラクトのプロパティは、サポートされている言語ごとに異なる方法で処理されます。

**Example**  

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket",
  corsConfiguration: {
    corsRules: [{
          allowedOrigins: ["*"],
          allowedMethods: ["GET"]
    }]
  }
});
```

```
const bucket = new s3.CfnBucket(this, "amzn-s3-demo-bucket", {
  bucketName: "amzn-s3-demo-bucket",
  corsConfiguration: {
    corsRules: [{
          allowedOrigins: ["*"],
          allowedMethods: ["GET"]
    }]
  }
});
```
Python では、これらのプロパティは L1 コンストラクトの内部クラスとして定義された型として表現されます。たとえば、`CfnBucket` のオプションプロパティ `cors_configuration` には、`CfnBucket.CorsConfigurationProperty` 型のラッパーが必要です。ここでは、`CfnBucket` インスタンスで `cors_configuration` を定義しています。  

```
bucket = CfnBucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket",
    cors_configuration=CfnBucket.CorsConfigurationProperty(
        cors_rules=[CfnBucket.CorsRuleProperty(
            allowed_origins=["*"],
            allowed_methods=["GET"]
        )]
    )
)
```
Java では、これらのプロパティは L1 コンストラクトの内部クラスとして定義された型として表現されます。たとえば、`CfnBucket` のオプションプロパティ `corsConfiguration` には、`CfnBucket.CorsConfigurationProperty` 型のラッパーが必要です。ここでは、`CfnBucket` インスタンスで `corsConfiguration` を定義しています。  

```
CfnBucket bucket = CfnBucket.Builder.create(this, "amzn-s3-demo-bucket")
                        .bucketName("amzn-s3-demo-bucket")
                        .corsConfiguration(new CfnBucket.CorsConfigurationProperty.Builder()
                            .corsRules(Arrays.asList(new CfnBucket.CorsRuleProperty.Builder()
                                .allowedOrigins(Arrays.asList("*"))
                                .allowedMethods(Arrays.asList("GET"))
                                .build()))
                            .build())
                        .build();
```
C\$1 では、これらのプロパティは L1 コンストラクトの内部クラスとして定義された型として表現されます。たとえば、`CfnBucket` のオプションプロパティ `CorsConfiguration` には、`CfnBucket.CorsConfigurationProperty` 型のラッパーが必要です。ここでは、`CfnBucket` インスタンスで `CorsConfiguration` を定義しています。  

```
var bucket = new CfnBucket(this, "amzn-s3-demo-bucket", new CfnBucketProps
{
    BucketName = "amzn-s3-demo-bucket",
    CorsConfiguration = new CfnBucket.CorsConfigurationProperty
    {
        CorsRules = new object[] {
            new CfnBucket.CorsRuleProperty
            {
                AllowedOrigins = new string[] { "*" },
                AllowedMethods = new string[] { "GET" },
            }
        }
    }
});
```
Go では、これらの型は L1 コンストラクトの名前、アンダースコア、プロパティ名を使用して命名されます。たとえば、`CfnBucket` のオプションプロパティ `CorsConfiguration` には、`CfnBucket_CorsConfigurationProperty` 型のラッパーが必要です。ここでは、`CfnBucket` インスタンスで `CorsConfiguration` を定義しています。  

```
	awss3.NewCfnBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.CfnBucketProps{
		BucketName: jsii.String("amzn-s3-demo-bucket"),
		CorsConfiguration: &awss3.CfnBucket_CorsConfigurationProperty{
			CorsRules: []awss3.CorsRule{
				awss3.CorsRule{
					AllowedOrigins: jsii.Strings("*"),
					AllowedMethods: &[]awss3.HttpMethods{"GET"},
				},
			},
		},
	})
```

**重要**  
L1 コンストラクトで L2 プロパティタイプを使用することはできません。その逆も同様です。L1 コンストラクトを使用する場合は、使用している L1 コンストラクトに定義されているタイプを必ず使用してください。他の L1 コンストラクトの型を使用しないでください (名前が同じものもありますが、同じ型ではありません)。  
言語固有の API リファレンスの中には、現在 L1 プロパティタイプへのパスにエラーがあるか、これらのクラスがまったく記載されていないものがあります。これは近いうちに修正したいと考えています。それまでの間、このような型は常に、それらが使用される L1 コンストラクトの内部クラスであることに注意してください。

#### 他のコンストラクトからのリソースの参照
<a name="constructs-resource-references"></a>

他の AWS リソースを参照するコンストラクトプロパティを設定する場合、2 つの同等のオプションがあります。
+  **文字列参照**: ARNs、名前、その他のリソース識別子などの明示的な文字列値を渡す
+  **オブジェクト参照**: コンストラクトオブジェクトを直接渡します。これにより、プロパティが期待する識別子タイプを決定する必要がなくなります。CDK がそれを処理します。

##### 文字列参照の使用
<a name="_using_string_references"></a>

ARNs、その他のリソース識別子などの明示的な文字列値を渡すことができます。このアプローチはすべてのプロパティで機能し、複雑なオブジェクト内のネストされたプロパティに必要です。

次の例では、L2 コンストラクト () を使用して定義されたロールを持つ L1 コンストラクト () を使用して Lambda 関数を作成します`Role`。`CfnFunction` L2 ロールの ARN は `role`プロパティに渡されます。

**Example**  

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    ),
  ],
});

const myFunction = new lambda.CfnFunction(this, 'HelloWorldFunction', {
  runtime: 'nodejs24.x',
  role: role.roleArn, // Pass the ARN string explicitly
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});
```

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    )
  ]
});

const myFunction = new lambda.CfnFunction(this, "HelloWorldFunction", {
  runtime: 'nodejs24.x',
  role: role.roleArn, // Pass the ARN string explicitly
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});
```

```
role = iam.Role(self, "MyRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
    managed_policies=[
        iam.ManagedPolicy.from_aws_managed_policy_name(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ]
)

my_function = _lambda.CfnFunction(self, "HelloWorldFunction",
    runtime="nodejs24.x",
    role=role.role_arn,  # Pass the ARN string explicitly
    handler="index.handler",
    code=_lambda.CfnFunction.CodeProperty(
        zip_file=
        """
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        """
    )
)
```

```
Role role = Role.Builder.create(this, "MyRole")
    .assumedBy(new ServicePrincipal("lambda.amazonaws.com"))
    .managedPolicies(Arrays.asList(
        ManagedPolicy.fromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ))
    .build();

CfnFunction myFunction = CfnFunction.Builder.create(this, "HelloWorldFunction")
    .runtime("nodejs24.x")
    .role(role.getRoleArn())  // Pass the ARN string explicitly
    .handler("index.handler")
    .code(CfnFunction.CodeProperty.builder()
        .zipFile(
            "exports.handler = async function(event) {" +
            "  return {" +
            "    statusCode: 200," +
            "    body: JSON.stringify('Hello World!')," +
            "  };" +
            "};")
        .build())
    .build();
```

```
var role = new Role(this, "MyRole", new RoleProps
{
    AssumedBy = new ServicePrincipal("lambda.amazonaws.com"),
    ManagedPolicies = new[]
    {
        ManagedPolicy.FromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    }
});

var myFunction = new CfnFunction(this, "HelloWorldFunction", new CfnFunctionProps
{
    Runtime = "nodejs24.x",
    Role = role.RoleArn,  // Pass the ARN string explicitly
    Handler = "index.handler",
    Code = new CfnFunction.CodeProperty
    {
        ZipFile = @"
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        "
    }
});
```

```
role := awsiam.NewRole(stack, jsii.String("MyRole"), &awsiam.RoleProps{
	AssumedBy: awsiam.NewServicePrincipal(jsii.String("lambda.amazonaws.com"), nil),
	ManagedPolicies: &[]awsiam.IManagedPolicy{
		awsiam.ManagedPolicy_FromAwsManagedPolicyName(jsii.String("service-role/AWSLambdaBasicExecutionRole")),
	},
})

myFunction := awslambda.NewCfnFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.CfnFunctionProps{
	Runtime: jsii.String("nodejs24.x"),
	Role:    role.RoleArn(), // Pass the ARN string explicitly
	Handler: jsii.String("index.handler"),
	Code: &awslambda.CfnFunction_CodeProperty{
		ZipFile: jsii.String(`
		exports.handler = async function(event) {
		  return {
		    statusCode: 200,
		    body: JSON.stringify('Hello World!'),
		  };
		};
		`),
	},
})
```

##### オブジェクトリファレンスの使用
<a name="_using_object_references"></a>

選択したプロパティでは、コンストラクトオブジェクトを手動で抽出する代わりに、コンストラクトオブジェクトを直接渡すことができます。オブジェクト参照のサポートはプロパティによって異なり、新しいプロパティが追加されると時間の経過とともに拡張される可能性があります。

コンストラクトの でオブジェクト参照を渡すと`props`、CDK はそれを適切な文字列値 (ARN、名前、その他の識別子など) に解決します。後でコンストラクトインスタンスの対応するプロパティにアクセスすると、元のオブジェクトリファレンスではなく、この解決された文字列値が表示されます。

オブジェクト参照は、コンストラクトの最上位プロパティでのみ機能します。複雑なオブジェクト内にネストされたプロパティには、明示的な文字列値が必要です。

次の例は、同じ Lambda 関数を示していますが、ロールの ARN 文字列の代わりにロールオブジェクトを使用します。

**Example**  

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    ),
  ],
});

const myFunction = new lambda.CfnFunction(this, 'HelloWorldFunction', {
  runtime: 'nodejs24.x',
  role: role, // CDK resolves to role ARN automatically
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});

// After creation, myFunction.role contains the resolved ARN string
```

```
const role = new iam.Role(this, 'MyRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName(
      'service-role/AWSLambdaBasicExecutionRole'
    )
  ]
});

const myFunction = new lambda.CfnFunction(this, "HelloWorldFunction", {
  runtime: 'nodejs24.x',
  role: role, // CDK resolves to role ARN automatically
  handler: 'index.handler',
  code: {
    zipFile: `
    exports.handler = async function(event) {
      return {
        statusCode: 200,
        body: JSON.stringify('Hello World!'),
      };
    };
  `}
});

// After creation, myFunction.role contains the resolved ARN string
```

```
role = iam.Role(self, "MyRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
    managed_policies=[
        iam.ManagedPolicy.from_aws_managed_policy_name(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ]
)

my_function = _lambda.CfnFunction(self, "HelloWorldFunction",
    runtime="nodejs24.x",
    role=role,  # CDK resolves to role ARN automatically
    handler="index.handler",
    code=_lambda.CfnFunction.CodeProperty(
        zip_file=
        """
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        """
    )
)

# After creation, my_function.role contains the resolved ARN string
```

```
Role role = Role.Builder.create(this, "MyRole")
    .assumedBy(new ServicePrincipal("lambda.amazonaws.com"))
    .managedPolicies(Arrays.asList(
        ManagedPolicy.fromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    ))
    .build();

CfnFunction myFunction = CfnFunction.Builder.create(this, "HelloWorldFunction")
    .runtime("nodejs24.x")
    .role(role)  // CDK resolves to role ARN automatically
    .handler("index.handler")
    .code(CfnFunction.CodeProperty.builder()
        .zipFile(
            "exports.handler = async function(event) {" +
            "  return {" +
            "    statusCode: 200," +
            "    body: JSON.stringify('Hello World!')," +
            "  };" +
            "};")
        .build())
    .build();

// After creation, myFunction.getRole() contains the resolved ARN string
```

```
var role = new Role(this, "MyRole", new RoleProps
{
    AssumedBy = new ServicePrincipal("lambda.amazonaws.com"),
    ManagedPolicies = new[]
    {
        ManagedPolicy.FromAwsManagedPolicyName(
            "service-role/AWSLambdaBasicExecutionRole"
        )
    }
});

var myFunction = new CfnFunction(this, "HelloWorldFunction", new CfnFunctionProps
{
    Runtime = "nodejs24.x",
    Role = role,  // CDK resolves to role ARN automatically
    Handler = "index.handler",
    Code = new CfnFunction.CodeProperty
    {
        ZipFile = @"
        exports.handler = async function(event) {
          return {
            statusCode: 200,
            body: JSON.stringify('Hello World!'),
          };
        };
        "
    }
});

// After creation, myFunction.Role contains the resolved ARN string
```

```
role := awsiam.NewRole(stack, jsii.String("MyRole"), &awsiam.RoleProps{
	AssumedBy: awsiam.NewServicePrincipal(jsii.String("lambda.amazonaws.com"), nil),
	ManagedPolicies: &[]awsiam.IManagedPolicy{
		awsiam.ManagedPolicy_FromAwsManagedPolicyName(jsii.String("service-role/AWSLambdaBasicExecutionRole")),
	},
})

myFunction := awslambda.NewCfnFunction(stack, jsii.String("HelloWorldFunction"), &awslambda.CfnFunctionProps{
	Runtime: jsii.String("nodejs24.x"),
	Role:    role, // CDK resolves to role ARN automatically
	Handler: jsii.String("index.handler"),
	Code: &awslambda.CfnFunction_CodeProperty{
		ZipFile: jsii.String(`
		exports.handler = async function(event) {
		  return {
		    statusCode: 200,
		    body: JSON.stringify('Hello World!'),
		  };
		};
		`),
	},
})

// After creation, *myFunction.Role() contains the resolved ARN string
```

### L2 コンストラクトの使用
<a name="constructs-using"></a>

以下の例では、[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) L2 コンストラクトからオブジェクトを作成して、Amazon S3 バケットを定義します。

**Example**  

```
import * as s3 from 'aws-cdk-lib/aws-s3';

// "this" is HelloCdkStack
new s3.Bucket(this, 'MyFirstBucket', {
  versioned: true
});
```

```
const s3 = require('aws-cdk-lib/aws-s3');

// "this" is HelloCdkStack
new s3.Bucket(this, 'MyFirstBucket', {
  versioned: true
});
```

```
import aws_cdk.aws_s3 as s3

# "self" is HelloCdkStack
s3.Bucket(self, "MyFirstBucket", versioned=True)
```

```
import software.amazon.awscdk.services.s3.*;

public class HelloCdkStack extends Stack {
    public HelloCdkStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public HelloCdkStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Bucket.Builder.create(this, "MyFirstBucket")
                .versioned(true).build();
    }
}
```

```
using Amazon.CDK.AWS.S3;

// "this" is HelloCdkStack
new Bucket(this, "MyFirstBucket", new BucketProps
{
    Versioned = true
});
```

```
import (
	"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
	"github.com/aws/jsii-runtime-go"
)

// stack is HelloCdkStack
awss3.NewBucket(stack, jsii.String("MyFirstBucket"), &awss3.BucketProps{
		Versioned: jsii.Bool(true),
	})
```

 `MyFirstBucket` は、 AWS CloudFormation が作成するバケットの名前ではありません。これは、CDK アプリケーションのコンテキスト内で新しいコンストラクトに与えられる論理識別子です。[physicalName](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Resource.html#physicalname) 値は、 AWS CloudFormation リソースに名前を付けるために使用されます。

## サードパーティーのコンストラクトの使用
<a name="constructs-work-third"></a>

 [Construct Hub ](https://constructs.dev/search?q=&cdk=aws-cdk&cdkver=2&sort=downloadsDesc&offset=0)は、、サードパーティー AWS、オープンソース CDK コミュニティから追加のコンストラクトを発見するのに役立つリソースです。

### 独自のコンストラクトの作成
<a name="constructs-author"></a>

既存のコンストラクトを使用するだけでなく、独自のコンストラクトを記述し、誰でもアプリで使用できるようにすることもできます。 AWS CDK では、すべてのコンストラクトが等しくなります。コンストラクトライブラリからの AWS コンストラクトは、NPM、、Mavenまたは を介して公開されたサードパーティーライブラリからのコンストラクトと同じように扱われますPyPI。また、社内のパッケージリポジトリに公開されたコンストラクトも同じように扱われます。

新しいコンストラクトを宣言するには、[Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/constructs.Construct.html) 基底クラスを拡張するクラスを `constructs` パッケージで作成し、初期化引数のパターンに従います。

以下の例は、Amazon S3 バケットを表すコンストラクトを宣言する方法を示しています。S3 バケットは、誰かがファイルをアップロードするたびに Amazon Simple Notiﬁcation Service (Amazon SNS) 通知を送信します。

**Example**  

```
export interface NotifyingBucketProps {
  prefix?: string;
}

export class NotifyingBucket extends Construct {
  constructor(scope: Construct, id: string, props: NotifyingBucketProps = {}) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    const topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic),
      { prefix: props.prefix });
  }
}
```

```
class NotifyingBucket extends Construct {
  constructor(scope, id, props = {}) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    const topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(topic),
      { prefix: props.prefix });
  }
}

module.exports = { NotifyingBucket }
```

```
class NotifyingBucket(Construct):

    def __init__(self, scope: Construct, id: str, *, prefix=None):
        super().__init__(scope, id)
        bucket = s3.Bucket(self, "bucket")
        topic = sns.Topic(self, "topic")
        bucket.add_object_created_notification(s3notify.SnsDestination(topic),
            s3.NotificationKeyFilter(prefix=prefix))
```

```
public class NotifyingBucket extends Construct {

    public NotifyingBucket(final Construct scope, final String id) {
        this(scope, id, null, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props) {
        this(scope, id, props, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final String prefix) {
        this(scope, id, null, prefix);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) {
        super(scope, id);

        Bucket bucket = new Bucket(this, "bucket");
        Topic topic = new Topic(this, "topic");
        if (prefix != null)
            bucket.addObjectCreatedNotification(new SnsDestination(topic),
                NotificationKeyFilter.builder().prefix(prefix).build());
     }
}
```

```
public class NotifyingBucketProps : BucketProps
{
    public string Prefix { get; set; }
}

public class NotifyingBucket : Construct
{
    public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id)
    {
        var bucket = new Bucket(this, "bucket");
        var topic = new Topic(this, "topic");
        bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter
        {
            Prefix = props?.Prefix
        });
    }
}
```

```
type NotifyingBucketProps struct {
	awss3.BucketProps
	Prefix *string
}

func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) awss3.Bucket {
	var bucket awss3.Bucket
	if props == nil {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil)
	} else {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps)
	}
	topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil)
	if props == nil {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic))
	} else {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{
			Prefix: props.Prefix,
		})
	}
	return bucket
}
```

**注記**  
`NotifyingBucket` コンストラクトは、`Bucket` ではなく、`Construct` を継承しています。これは、Amazon S3 バケットと Amazon SNS トピックをバンドルするために、継承ではなく構成を使用しているためです。一般的に、 AWS CDK コンストラクトを開発する場合、コンポジションは継承よりも優先されます。

`NotifyingBucket` コンストラクターは、`scope`、`id`、`props` という典型的なコンストラクトの署名を持っています。最後に挙げた引数 `props` は、props はすべてオプションであるため、オプション (デフォルト値 `{}`) になります。(規定クラス `Construct` は `props` 引数を取りません)。このコンストラクトのインスタンスは、`props` なしでアプリに定義できます。たとえば以下のようになります。

**Example**  

```
new NotifyingBucket(this, 'MyNotifyingBucket');
```

```
new NotifyingBucket(this, 'MyNotifyingBucket');
```

```
NotifyingBucket(self, "MyNotifyingBucket")
```

```
new NotifyingBucket(this, "MyNotifyingBucket");
```

```
new NotifyingBucket(this, "MyNotifyingBucket");
```

```
NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), nil)
```

または、`props` (Java では追加パラメータ) を使用して、フィルタリングするパスプレフィックスを指定できます。たとえば以下のようになります。

**Example**  

```
new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });
```

```
new NotifyingBucket(this, 'MyNotifyingBucket', { prefix: 'images/' });
```

```
NotifyingBucket(self, "MyNotifyingBucket", prefix="images/")
```

```
new NotifyingBucket(this, "MyNotifyingBucket", "/images");
```

```
new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps
{
    Prefix = "/images"
});
```

```
NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{
	Prefix: jsii.String("images/"),
})
```

通常、コンストラクト上のいくつかのプロパティまたはメソッドも公開する必要があります。コンストラクトの背後にトピックが隠れてしまう形では、コンストラクトのユーザーがサブスクライブできなくなるため、あまり有益とは言えません。`topic` プロパティを追加すると、以下の例に示すように、利用者が内部トピックにアクセスできるようになります。

**Example**  

```
export class NotifyingBucket extends Construct {
  public readonly topic: sns.Topic;

  constructor(scope: Construct, id: string, props: NotifyingBucketProps) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    this.topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix });
  }
}
```

```
class NotifyingBucket extends Construct {

  constructor(scope, id, props) {
    super(scope, id);
    const bucket = new s3.Bucket(this, 'bucket');
    this.topic = new sns.Topic(this, 'topic');
    bucket.addObjectCreatedNotification(new s3notify.SnsDestination(this.topic), { prefix: props.prefix });
  }
}

module.exports = { NotifyingBucket };
```

```
class NotifyingBucket(Construct):

    def __init__(self, scope: Construct, id: str, *, prefix=None, **kwargs):
        super().__init__(scope, id)
        bucket = s3.Bucket(self, "bucket")
        self.topic = sns.Topic(self, "topic")
        bucket.add_object_created_notification(s3notify.SnsDestination(self.topic),
            s3.NotificationKeyFilter(prefix=prefix))
```

```
public class NotifyingBucket extends Construct {

    public Topic topic = null;

    public NotifyingBucket(final Construct scope, final String id) {
        this(scope, id, null, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props) {
        this(scope, id, props, null);
    }

    public NotifyingBucket(final Construct scope, final String id, final String prefix) {
        this(scope, id, null, prefix);
    }

    public NotifyingBucket(final Construct scope, final String id, final BucketProps props, final String prefix) {
        super(scope, id);

        Bucket bucket = new Bucket(this, "bucket");
        topic = new Topic(this, "topic");
        if (prefix != null)
            bucket.addObjectCreatedNotification(new SnsDestination(topic),
                NotificationKeyFilter.builder().prefix(prefix).build());
     }
}
```

```
public class NotifyingBucket : Construct
{
    public readonly Topic topic;

    public NotifyingBucket(Construct scope, string id, NotifyingBucketProps props = null) : base(scope, id)
    {
        var bucket = new Bucket(this, "bucket");
        topic = new Topic(this, "topic");
        bucket.AddObjectCreatedNotification(new SnsDestination(topic), new NotificationKeyFilter
        {
            Prefix = props?.Prefix
        });
    }
}
```
Go でこれを実行するには、少し追加の準備が必要です。元の `NewNotifyingBucket` 関数は、そのままでは `awss3.Bucket` を返します。そこで、`NotifyingBucket` 構造体を作成して、`topic` メンバーを含めるように `Bucket` を拡張する必要があります。そうすることで、この関数はこの型を返すようになります。  

```
type NotifyingBucket struct {
	awss3.Bucket
	topic awssns.Topic
}

func NewNotifyingBucket(scope constructs.Construct, id *string, props *NotifyingBucketProps) NotifyingBucket {
	var bucket awss3.Bucket
	if props == nil {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), nil)
	} else {
		bucket = awss3.NewBucket(scope, jsii.String(*id+"Bucket"), &props.BucketProps)
	}
	topic := awssns.NewTopic(scope, jsii.String(*id+"Topic"), nil)
	if props == nil {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic))
	} else {
		bucket.AddObjectCreatedNotification(awss3notifications.NewSnsDestination(topic), &awss3.NotificationKeyFilter{
			Prefix: props.Prefix,
		})
	}
	var nbucket NotifyingBucket
	nbucket.Bucket = bucket
	nbucket.topic = topic
	return nbucket
}
```

これで、利用者はトピックをサブスクライブできるようになりました。たとえば以下のようになります。

**Example**  

```
const queue = new sqs.Queue(this, 'NewImagesQueue');
const images = new NotifyingBucket(this, '/images');
images.topic.addSubscription(new sns_sub.SqsSubscription(queue));
```

```
const queue = new sqs.Queue(this, 'NewImagesQueue');
const images = new NotifyingBucket(this, '/images');
images.topic.addSubscription(new sns_sub.SqsSubscription(queue));
```

```
queue = sqs.Queue(self, "NewImagesQueue")
images = NotifyingBucket(self, prefix="Images")
images.topic.add_subscription(sns_sub.SqsSubscription(queue))
```

```
NotifyingBucket images = new NotifyingBucket(this, "MyNotifyingBucket", "/images");
images.topic.addSubscription(new SqsSubscription(queue));
```

```
var queue = new Queue(this, "NewImagesQueue");
var images = new NotifyingBucket(this, "MyNotifyingBucket", new NotifyingBucketProps
{
    Prefix = "/images"
});
images.topic.AddSubscription(new SqsSubscription(queue));
```

```
	queue := awssqs.NewQueue(stack, jsii.String("NewImagesQueue"), nil)
	images := NewNotifyingBucket(stack, jsii.String("MyNotifyingBucket"), &NotifyingBucketProps{
		Prefix: jsii.String("/images"),
	})
	images.topic.AddSubscription(awssnssubscriptions.NewSqsSubscription(queue, nil))
```

## 詳細情報
<a name="constructs-learn"></a>

以下のビデオでは、CDK コンストラクトの包括的な概要と、CDK アプリケーションでの CDK コンストラクトの使用方法について説明します。

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/PzU-i0rJPGw?rel=0/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/PzU-i0rJPGw?rel=0)
