

这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段，并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Aspections 和 AWS CDK
<a name="aspects"></a>

方面是一种将操作应用于给定范围内所有构造的方法。方面可以通过添加标签等方式修改构造。或者可以验证一些有关构造状态的信息，例如确保所有存储桶均已加密。

要将某方面应用于相同范围内的一个构造和所有构造，请使用新方面调用 ` [Aspects](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Aspects.html#static-ofscope).of(<SCOPE>).add()`，如以下示例所示。

**Example**  

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.of(my_construct).add(SomeAspect(...))
```

```
Aspects.of(myConstruct).add(new SomeAspect(...));
```

```
Aspects.Of(myConstruct).add(new SomeAspect(...));
```

```
awscdk.Aspects_Of(stack).Add(awscdk.NewTag(...))
```

 AWS CDK 使用方面来[标记资源](tagging.md)，但该框架也可以用于其他目的。例如，您可以使用它来验证或更改由更高级别的构造为您定义的 AWS CloudFormation 资源。

## 方面 vs Mixins
<a name="aspects-vs-mixins"></a>

Aspects 和 [Mixin](mixins.md) s 都修改了构造，但它们在应用的时间和方式上有所不同：


| 功能 | 方面 | mixins | 
| --- | --- | --- | 
|   **应用时**   |  在合成过程中，在所有其他代码都运行完毕之后。  |  接到电话时立`.with()`即。  | 
|   **范围**   |  给定作用域中的所有构造，包括稍后添加的构造。  |  只有你明确应用它们的构造。  | 
|   **样式**   |  声明式 — 您设置了规则，CDK 就会应用该规则。  |  势在必行 — 您可以选择申请什么以及在何处申请。  | 
|   **适用于**   |  验证、合规、标记、广泛的政策。  |  为单个资源添加特定功能。  | 

如果要在整个应用程序中强制执行规则或验证结构是否符合特定标准，请使用 Aspects。如果要向特定构造添加特定功能，请使用 Mixins。

Aspects 和 Mixins 可以一起使用。例如，您可以使用 Mixins 来配置单个资源，并使用 Aspects 来验证堆栈中的所有资源是否符合组织的安全要求。

## 方面详细说明
<a name="aspects-detail"></a>

方面采用[访客模式](https://en.wikipedia.org/wiki/Visitor_pattern)。方面是实现以下接口的类。

**Example**  

```
interface IAspect {
   visit(node: IConstruct): void;}
```
JavaScript 没有接口作为语言功能。因此，方面只是类的实例，其 `visit` 方法接受待操作节点。
Python 并无接口用作语言功能。因此，方面只是类的实例，其 `visit` 方法接受待操作节点。

```
public interface IAspect {
    public void visit(Construct node);
}
```

```
public interface IAspect
{
    void Visit(IConstruct node);
}
```

```
type IAspect interface {
  Visit(node constructs.IConstruct)
}
```

在调用 `Aspects.of(<SCOPE>).add(…​)` 时，构造会将方面添加到内部方面列表中。您可以通过 `Aspects.of(<SCOPE>)` 获取列表。

在[准备阶段](deploy.md#deploy-how-synth-app)， AWS CDK 按自上而下的顺序为构造及其每个子对象调用对象`visit`的方法。

`visit` 方法可以自由更改构造中的任何内容。在强类型语言中，在访问特定于构造的属性或方法之前，将接收到的构造转换为更具体的类型。

方面不会跨 `Stage` 构造边界传播，因为定义之后 `Stages` 独立且不可变。若希望方面访问 `Stage` 内部构造，则将方面应用于 `Stage` 构造本身（或更低版本）。

## 示例
<a name="aspects-example"></a>

以下示例验证堆栈中创建的所有存储桶是否均启用版本控制。方面为验证失败的构造添加错误注释。这会导致 `synth` 操作失败并防止部署生成的云程序集。

**Example**  

```
class BucketVersioningChecker implements IAspect {
  public visit(node: IConstruct): void {
    // See that we're dealing with a CfnBucket
    if (node instanceof s3.CfnBucket) {

      // Check for versioning property, exclude the case where the property
      // can be a token (IResolvable).
      if (!node.versioningConfiguration
        || (!Tokenization.isResolvable(node.versioningConfiguration)
            && node.versioningConfiguration.status !== 'Enabled')) {
        Annotations.of(node).addError('Bucket versioning is not enabled');
      }
    }
  }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
class BucketVersioningChecker {
   visit(node) {
    // See that we're dealing with a CfnBucket
    if ( node instanceof s3.CfnBucket) {

      // Check for versioning property, exclude the case where the property
      // can be a token (IResolvable).
      if (!node.versioningConfiguration
        || !Tokenization.isResolvable(node.versioningConfiguration)
            && node.versioningConfiguration.status !== 'Enabled')) {
        Annotations.of(node).addError('Bucket versioning is not enabled');
      }
    }
  }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
@jsii.implements(cdk.IAspect)
class BucketVersioningChecker:

  def visit(self, node):
    # See that we're dealing with a CfnBucket
    if isinstance(node, s3.CfnBucket):

      # Check for versioning property, exclude the case where the property
      # can be a token (IResolvable).
      if (not node.versioning_configuration or
              not Tokenization.is_resolvable(node.versioning_configuration)
                  and node.versioning_configuration.status != "Enabled"):
          Annotations.of(node).add_error('Bucket versioning is not enabled')

# Later, apply to the stack
Aspects.of(stack).add(BucketVersioningChecker())
```

```
public class BucketVersioningChecker implements IAspect
{
    @Override
    public void visit(Construct node)
    {
        // See that we're dealing with a CfnBucket
        if (node instanceof CfnBucket)
        {
            CfnBucket bucket = (CfnBucket)node;
            Object versioningConfiguration = bucket.getVersioningConfiguration();
            if (versioningConfiguration == null ||
                    !Tokenization.isResolvable(versioningConfiguration.toString()) &&
                    !versioningConfiguration.toString().contains("Enabled"))
                Annotations.of(bucket.getNode()).addError("Bucket versioning is not enabled");
        }
    }
}

// Later, apply to the stack
Aspects.of(stack).add(new BucketVersioningChecker());
```

```
class BucketVersioningChecker : Amazon.Jsii.Runtime.Deputy.DeputyBase, IAspect
{
    public void Visit(IConstruct node)
    {
        // See that we're dealing with a CfnBucket
        if (node is CfnBucket)
        {
            var bucket = (CfnBucket)node;
            if (bucket.VersioningConfiguration is null ||
                    !Tokenization.IsResolvable(bucket.VersioningConfiguration) &&
                    !bucket.VersioningConfiguration.ToString().Contains("Enabled"))
                Annotations.Of(bucket.Node).AddError("Bucket versioning is not enabled");
        }
    }
}

// Later, apply to the stack
Aspects.Of(stack).add(new BucketVersioningChecker());
```