diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
index 7f61c504e07b85f4f81ffaebc3dd7d1338a20c44..533b026236ab8876082887ccf65b3c90aadf20a6 100644
--- a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
+++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php
@@ -42,6 +42,9 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
 
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
+    if ($context_configuration) {
+      @trigger_error('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980', E_USER_DEPRECATED);
+    }
     $this->context = $this->createContextFromConfiguration($context_configuration);
   }
 
diff --git a/core/lib/Drupal/Core/Block/BlockBase.php b/core/lib/Drupal/Core/Block/BlockBase.php
index 7076da42af71c6b76732b37d45c6361d32cb5ec5..ab6948f8ca9209d9474fd6c21952671c73635a1b 100644
--- a/core/lib/Drupal/Core/Block/BlockBase.php
+++ b/core/lib/Drupal/Core/Block/BlockBase.php
@@ -3,7 +3,9 @@
 namespace Drupal\Core\Block;
 
 use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 use Drupal\Core\Plugin\PluginWithFormsInterface;
 use Drupal\Core\Render\PreviewFallbackInterface;
 
@@ -16,9 +18,10 @@
  *
  * @ingroup block_api
  */
-abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface {
+abstract class BlockBase extends PluginBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface, ContextAwarePluginInterface {
 
   use BlockPluginTrait;
+  use ContextAwarePluginTrait;
   use ContextAwarePluginAssignmentTrait;
 
 }
diff --git a/core/lib/Drupal/Core/Condition/ConditionManager.php b/core/lib/Drupal/Core/Condition/ConditionManager.php
index 2bacf2a0e93328922ff25622f34f2c28240c9082..be4a4b5f89a6919c1a6c856a8021ba5fd6acebb6 100644
--- a/core/lib/Drupal/Core/Condition/ConditionManager.php
+++ b/core/lib/Drupal/Core/Condition/ConditionManager.php
@@ -60,6 +60,7 @@ public function createInstance($plugin_id, array $configuration = []) {
 
     // If we receive any context values via config set it into the plugin.
     if (!empty($configuration['context'])) {
+      @trigger_error('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980', E_USER_DEPRECATED);
       foreach ($configuration['context'] as $name => $context) {
         $plugin->setContextValue($name, $context);
       }
diff --git a/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php b/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php
index 088bd3735bf0e87874196132d81df339a755b70d..c9632a1d5c3d4829ded3b07e932060fce63893b8 100644
--- a/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php
+++ b/core/lib/Drupal/Core/Executable/ExecutablePluginBase.php
@@ -2,13 +2,18 @@
 
 namespace Drupal\Core\Executable;
 
-use Drupal\Core\Plugin\ContextAwarePluginBase;
 use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 
 /**
  * Provides the basic architecture for executable plugins.
  */
-abstract class ExecutablePluginBase extends ContextAwarePluginBase implements ExecutableInterface {
+abstract class ExecutablePluginBase extends PluginBase implements ExecutableInterface, CacheableDependencyInterface, ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait;
 
   /**
    * Gets an array of definitions of available configuration options.
diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php
index c40c02783f58146d00bcaf54bda3f2b9b3043580..1be0e353a51b30e18fdea3783262121d179b1c73 100644
--- a/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php
+++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php
@@ -3,21 +3,20 @@
 namespace Drupal\Core\Plugin;
 
 use Drupal\Component\Plugin\ContextAwarePluginBase as ComponentContextAwarePluginBase;
-use Drupal\Component\Plugin\Exception\ContextException;
-use Drupal\Component\Plugin\PluginHelper;
-use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\TypedData\TypedDataTrait;
-use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
-use Drupal\Core\Plugin\Context\ContextInterface;
+
+@trigger_error(__NAMESPACE__ . '\ContextAwarePluginBase is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, use \Drupal\Core\Plugin\ContextAwarePluginTrait. See https://www.drupal.org/node/3120980', E_USER_DEPRECATED);
 
 /**
  * Base class for plugins that are context aware.
  */
 abstract class ContextAwarePluginBase extends ComponentContextAwarePluginBase implements ContextAwarePluginInterface, CacheableDependencyInterface {
+
+  use ContextAwarePluginTrait;
   use TypedDataTrait;
   use StringTranslationTrait;
   use DependencySerializationTrait;
@@ -38,139 +37,4 @@ protected function createContextFromConfiguration(array $context_configuration)
     return $contexts;
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * This code is identical to the Component in order to pick up a different
-   * Context class.
-   *
-   * @return \Drupal\Core\Plugin\Context\ContextInterface
-   *   The context object.
-   */
-  public function getContext($name) {
-    // Check for a valid context value.
-    if (!isset($this->context[$name])) {
-      $this->context[$name] = new Context($this->getContextDefinition($name));
-    }
-    return $this->context[$name];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setContext($name, ComponentContextInterface $context) {
-    // Check that the context passed is an instance of our extended interface.
-    if (!$context instanceof ContextInterface) {
-      throw new ContextException("Passed $name context must be an instance of \\Drupal\\Core\\Plugin\\Context\\ContextInterface");
-    }
-    parent::setContext($name, $context);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setContextValue($name, $value) {
-    $this->setContext($name, Context::createFromContext($this->getContext($name), $value));
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContextMapping() {
-    $configuration = PluginHelper::isConfigurable($this) ? $this->getConfiguration() : $this->configuration;
-    return isset($configuration['context_mapping']) ? $configuration['context_mapping'] : [];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setContextMapping(array $context_mapping) {
-    if (PluginHelper::isConfigurable($this)) {
-      $configuration = $this->getConfiguration();
-      $configuration['context_mapping'] = array_filter($context_mapping);
-      $this->setConfiguration($configuration);
-    }
-    else {
-      $this->configuration['context_mapping'] = $context_mapping;
-    }
-    return $this;
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface[]
-   */
-  public function getContextDefinitions() {
-    return parent::getContextDefinitions();
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface
-   */
-  public function getContextDefinition($name) {
-    return parent::getContextDefinition($name);
-  }
-
-  /**
-   * Wraps the context handler.
-   *
-   * @return \Drupal\Core\Plugin\Context\ContextHandlerInterface
-   */
-  protected function contextHandler() {
-    return \Drupal::service('context.handler');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheContexts() {
-    $cache_contexts = [];
-    // Applied contexts can affect the cache contexts when this plugin is
-    // involved in caching, collect and return them.
-    foreach ($this->getContexts() as $context) {
-      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
-      if ($context instanceof CacheableDependencyInterface) {
-        $cache_contexts = Cache::mergeContexts($cache_contexts, $context->getCacheContexts());
-      }
-    }
-    return $cache_contexts;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheTags() {
-    $tags = [];
-    // Applied contexts can affect the cache tags when this plugin is
-    // involved in caching, collect and return them.
-    foreach ($this->getContexts() as $context) {
-      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
-      if ($context instanceof CacheableDependencyInterface) {
-        $tags = Cache::mergeTags($tags, $context->getCacheTags());
-      }
-    }
-    return $tags;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCacheMaxAge() {
-    $max_age = Cache::PERMANENT;
-
-    // Applied contexts can affect the cache max age when this plugin is
-    // involved in caching, collect and return them.
-    foreach ($this->getContexts() as $context) {
-      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
-      if ($context instanceof CacheableDependencyInterface) {
-        $max_age = Cache::mergeMaxAges($max_age, $context->getCacheMaxAge());
-      }
-    }
-    return $max_age;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginInterface.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginInterface.php
index 67f53b69704f3b3a61556e2fa10b52e9e9c3865d..7b48f99347b18a83b29822e5ec3294a7c1644d27 100644
--- a/core/lib/Drupal/Core/Plugin/ContextAwarePluginInterface.php
+++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginInterface.php
@@ -8,6 +8,7 @@
  * An override of ContextAwarePluginInterface for documentation purposes.
  *
  * @see \Drupal\Component\Plugin\ContextAwarePluginInterface
+ * @see \Drupal\Core\Plugin\ContextAwarePluginTrait
  *
  * @ingroup plugin_api
  */
diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginTrait.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..5d3445618af85c68688f1e2a311712e20e61a5b4
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginTrait.php
@@ -0,0 +1,251 @@
+<?php
+
+namespace Drupal\Core\Plugin;
+
+use Drupal\Component\Plugin\ConfigurableInterface;
+use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
+use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface;
+use Drupal\Component\Plugin\Exception\ContextException;
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextInterface;
+use Symfony\Component\Validator\ConstraintViolationList;
+
+/**
+ * Provides a trait to add context-aware functionality to plugins.
+ *
+ * @see \Drupal\Core\Plugin\ContextAwarePluginInterface
+ *
+ * @ingroup plugin_api
+ */
+trait ContextAwarePluginTrait {
+
+  /**
+   * The data objects representing the context of this plugin.
+   *
+   * @var \Drupal\Core\Plugin\Context\ContextInterface[]
+   */
+  protected $context = [];
+
+  /**
+   * Tracks whether the context has been initialized from configuration.
+   *
+   * @var bool
+   *
+   * @todo Remove this in Drupal 10.0.x.
+   *   See https://www.drupal.org/project/drupal/issues/3153956.
+   *
+   * @internal
+   */
+  protected $initializedContextConfig = FALSE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContexts() {
+    // Make sure all context objects are initialized.
+    foreach ($this->getContextDefinitions() as $name => $definition) {
+      $this->getContext($name);
+    }
+    return $this->context;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @return \Drupal\Core\Plugin\Context\ContextInterface
+   *   The context object.
+   */
+  public function getContext($name) {
+    // @todo Remove this entire block in Drupal 10.0.x.
+    //   See https://www.drupal.org/project/drupal/issues/3153956.
+    if (!$this->initializedContextConfig) {
+      $this->initializedContextConfig = TRUE;
+      if ($this instanceof ConfigurableInterface) {
+        $configuration = $this->getConfiguration();
+      }
+      else {
+        $reflection = new \ReflectionProperty($this, 'configuration');
+        $reflection->setAccessible(TRUE);
+        $configuration = $reflection->getValue($this);
+      }
+
+      if (isset($configuration['context'])) {
+        @trigger_error('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980', E_USER_DEPRECATED);
+        foreach ($configuration['context'] as $key => $value) {
+          $context_definition = $this->getContextDefinition($key);
+          $this->context[$key] = new Context($context_definition, $value);
+        }
+      }
+    }
+
+    // Check for a valid context value.
+    if (!isset($this->context[$name])) {
+      $this->context[$name] = new Context($this->getContextDefinition($name));
+    }
+    return $this->context[$name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContext($name, ComponentContextInterface $context) {
+    // Check that the context passed is an instance of our extended interface.
+    if (!$context instanceof ContextInterface) {
+      throw new ContextException("Passed $name context must be an instance of \\Drupal\\Core\\Plugin\\Context\\ContextInterface");
+    }
+    $this->context[$name] = $context;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextValues() {
+    $values = [];
+    foreach ($this->getContextDefinitions() as $name => $definition) {
+      $values[$name] = isset($this->context[$name]) ? $this->context[$name]->getContextValue() : NULL;
+    }
+    return $values;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextValue($name) {
+    return $this->getContext($name)->getContextValue();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContextValue($name, $value) {
+    $this->setContext($name, Context::createFromContext($this->getContext($name), $value));
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getContextMapping() {
+    $configuration = $this instanceof ConfigurableInterface ? $this->getConfiguration() : $this->configuration;
+    return isset($configuration['context_mapping']) ? $configuration['context_mapping'] : [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContextMapping(array $context_mapping) {
+    if ($this instanceof ConfigurableInterface) {
+      $configuration = $this->getConfiguration();
+      $configuration['context_mapping'] = array_filter($context_mapping);
+      $this->setConfiguration($configuration);
+    }
+    else {
+      $this->configuration['context_mapping'] = $context_mapping;
+    }
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  abstract protected function getPluginDefinition();
+
+  /**
+   * {@inheritdoc}
+   *
+   * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface[]
+   */
+  public function getContextDefinitions() {
+    $definition = $this->getPluginDefinition();
+    if ($definition instanceof ContextAwarePluginDefinitionInterface) {
+      return $definition->getContextDefinitions();
+    }
+
+    return !empty($definition['context_definitions']) ? $definition['context_definitions'] : [];
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface
+   */
+  public function getContextDefinition($name) {
+    $definition = $this->getPluginDefinition();
+    if ($definition instanceof ContextAwarePluginDefinitionInterface) {
+      if ($definition->hasContextDefinition($name)) {
+        return $definition->getContextDefinition($name);
+      }
+    }
+    elseif (!empty($definition['context_definitions'][$name])) {
+      return $definition['context_definitions'][$name];
+    }
+    throw new ContextException(sprintf("The %s context is not a valid context.", $name));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateContexts() {
+    $violations = new ConstraintViolationList();
+
+    // @todo Implement the Symfony Validator component to let the validator
+    //   traverse and set property paths accordingly.
+    //   See https://www.drupal.org/project/drupal/issues/3153847.
+    foreach ($this->getContexts() as $context) {
+      $violations->addAll($context->validate());
+    }
+    return $violations;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheContexts() {
+    $cache_contexts = [];
+    // Applied contexts can affect the cache contexts when this plugin is
+    // involved in caching, collect and return them.
+    foreach ($this->getContexts() as $context) {
+      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
+      if ($context instanceof CacheableDependencyInterface) {
+        $cache_contexts = Cache::mergeContexts($cache_contexts, $context->getCacheContexts());
+      }
+    }
+    return $cache_contexts;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheTags() {
+    $tags = [];
+    // Applied contexts can affect the cache tags when this plugin is
+    // involved in caching, collect and return them.
+    foreach ($this->getContexts() as $context) {
+      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
+      if ($context instanceof CacheableDependencyInterface) {
+        $tags = Cache::mergeTags($tags, $context->getCacheTags());
+      }
+    }
+    return $tags;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheMaxAge() {
+    $max_age = Cache::PERMANENT;
+
+    // Applied contexts can affect the cache max age when this plugin is
+    // involved in caching, collect and return them.
+    foreach ($this->getContexts() as $context) {
+      /** @var $context \Drupal\Core\Cache\CacheableDependencyInterface */
+      if ($context instanceof CacheableDependencyInterface) {
+        $max_age = Cache::mergeMaxAges($max_age, $context->getCacheMaxAge());
+      }
+    }
+    return $max_age;
+  }
+
+}
diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageBase.php b/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageBase.php
index 415fed907ef5aa0cacea7c36f7d560261617c19e..41e63d148124df9c3804271162bba024c63ae035 100644
--- a/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageBase.php
+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageBase.php
@@ -2,9 +2,11 @@
 
 namespace Drupal\layout_builder\Plugin\SectionStorage;
 
+use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 use Drupal\layout_builder\Routing\LayoutBuilderRoutesTrait;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionStorageInterface;
@@ -13,8 +15,9 @@
 /**
  * Provides a base class for Section Storage types.
  */
-abstract class SectionStorageBase extends ContextAwarePluginBase implements SectionStorageInterface, TempStoreIdentifierInterface {
+abstract class SectionStorageBase extends PluginBase implements SectionStorageInterface, TempStoreIdentifierInterface, CacheableDependencyInterface {
 
+  use ContextAwarePluginTrait;
   use LayoutBuilderRoutesTrait;
 
   /**
diff --git a/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/SectionStorage/SimpleConfigSectionStorage.php b/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/SectionStorage/SimpleConfigSectionStorage.php
index a17ededaea7169e4bf73ee23f1a43649f181f707..f7316ec105178fada28e998c158a1038a2c75a1e 100644
--- a/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/SectionStorage/SimpleConfigSectionStorage.php
+++ b/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/SectionStorage/SimpleConfigSectionStorage.php
@@ -8,7 +8,8 @@
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Url;
 use Drupal\layout_builder\Plugin\SectionStorage\SectionStorageLocalTaskProviderInterface;
@@ -29,8 +30,9 @@
  *   }
  * )
  */
-class SimpleConfigSectionStorage extends ContextAwarePluginBase implements SectionStorageInterface, SectionStorageLocalTaskProviderInterface, ContainerFactoryPluginInterface {
+class SimpleConfigSectionStorage extends PluginBase implements SectionStorageInterface, SectionStorageLocalTaskProviderInterface, ContainerFactoryPluginInterface {
 
+  use ContextAwarePluginTrait;
   use LayoutBuilderRoutesTrait;
   use SectionStorageTrait;
 
diff --git a/core/modules/node/tests/src/Kernel/NodeConditionTest.php b/core/modules/node/tests/src/Kernel/NodeConditionTest.php
index 0a9c6f7e201e5e66e42e8459f838deaa8e01d0c9..a52c0f3f42338b0322c57a0f04e2ddadc680a969 100644
--- a/core/modules/node/tests/src/Kernel/NodeConditionTest.php
+++ b/core/modules/node/tests/src/Kernel/NodeConditionTest.php
@@ -74,6 +74,16 @@ public function testConditions() {
     // Check a greater than 2 bundles summary scenario.
     $condition->setConfig('bundles', ['page' => 'page', 'article' => 'article', 'test' => 'test']);
     $this->assertEqual('The node bundle is page, article or test', $condition->summary());
+  }
+
+  /**
+   * @group legacy
+   */
+  public function testLegacy() {
+    $this->expectDeprecation('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980');
+    $manager = $this->container->get('plugin.manager.condition');
+    $article = Node::create(['type' => 'article', 'title' => $this->randomMachineName(), 'uid' => 1]);
+    $article->save();
 
     // Test Constructor injection.
     $condition = $manager->createInstance('node_type', ['bundles' => ['article' => 'article'], 'context' => ['node' => $article]]);
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockComplexContextBlock.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockComplexContextBlock.php
index e044e27e32204ffff8f50eb3c6897d0ba87cc661..f791811302fe3a42aeca8ed92dbc634dfdb9e573 100644
--- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockComplexContextBlock.php
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockComplexContextBlock.php
@@ -2,14 +2,18 @@
 
 namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
 
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 
 /**
  * Implementation of a complex context plugin used by Plugin API context tests.
  *
  * @see \Drupal\plugin_test\Plugin\MockBlockManager
  */
-class MockComplexContextBlock extends ContextAwarePluginBase {
+class MockComplexContextBlock extends PluginBase implements ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait;
 
   public function getTitle() {
     $user = $this->getContextValue('user');
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockUserNameBlock.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockUserNameBlock.php
index 6b4688d8acde250c2ab39785ca8f445e412b4efe..8ea56ede0eb5abcd89b203244c9e87700af0836c 100644
--- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockUserNameBlock.php
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/MockUserNameBlock.php
@@ -2,14 +2,18 @@
 
 namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
 
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 
 /**
  * Implementation of a user name block plugin used by Plugin API context test.
  *
  * @see \Drupal\plugin_test\Plugin\MockBlockManager
  */
-class MockUserNameBlock extends ContextAwarePluginBase {
+class MockUserNameBlock extends PluginBase implements ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait;
 
   public function getTitle() {
     $user = $this->getContextValue('user');
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/TypedDataStringBlock.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/TypedDataStringBlock.php
index b47d46b4fca76d80c55949385aa2f41ceb21b5e5..5658cbf4240a00dce3ff08aa03ddad399cb764c0 100644
--- a/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/TypedDataStringBlock.php
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/plugin_test/mock_block/TypedDataStringBlock.php
@@ -2,7 +2,9 @@
 
 namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
 
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 
 /**
  * Implementation of a String TypedData contextual block plugin used by Plugin
@@ -10,7 +12,9 @@
  *
  * @see \Drupal\plugin_test\Plugin\MockBlockManager
  */
-class TypedDataStringBlock extends ContextAwarePluginBase {
+class TypedDataStringBlock extends PluginBase implements ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait;
 
   public function getTitle() {
     return $this->getContextValue('string');
diff --git a/core/modules/user/tests/src/Kernel/Condition/UserRoleConditionTest.php b/core/modules/user/tests/src/Kernel/Condition/UserRoleConditionTest.php
index 73fa0546ead49188b130a1d8e94b5dc957f749c3..4bfb0588ef06b9b273722e2fc4a548937718e76b 100644
--- a/core/modules/user/tests/src/Kernel/Condition/UserRoleConditionTest.php
+++ b/core/modules/user/tests/src/Kernel/Condition/UserRoleConditionTest.php
@@ -135,10 +135,6 @@ public function testConditions() {
     $condition->setConfig('roles', [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]);
     $this->assertTrue($condition->execute(), 'Authenticated users pass role checks for authenticated.');
 
-    // Test Constructor injection.
-    $condition = $this->manager->createInstance('user_role', ['roles' => [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID], 'context' => ['user' => $this->authenticated]]);
-    $this->assertTrue($condition->execute(), 'Constructor injection of context and configuration working as anticipated.');
-
     // Check the negated summary.
     $condition->setConfig('negate', TRUE);
     $this->assertEqual($condition->summary(), 'The user is not a member of Authenticated user');
@@ -154,4 +150,14 @@ public function testConditions() {
     $this->assertEqual($condition->summary(), new FormattableMarkup('The user is a member of @roles', ['@roles' => $this->role->label()]));
   }
 
+  /**
+   * @group legacy
+   */
+  public function testLegacy() {
+    $this->expectDeprecation('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980');
+    // Test Constructor injection.
+    $condition = $this->manager->createInstance('user_role', ['roles' => [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID], 'context' => ['user' => $this->authenticated]]);
+    $this->assertTrue($condition->execute(), 'Constructor injection of context and configuration working as anticipated.');
+  }
+
 }
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginBaseTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginBaseTest.php
index fa25970de03ad84a2b2320be34a9e68233d1f1f2..2205e7c0715ecc42643adac66500406fcd397d07 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginBaseTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginBaseTest.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\KernelTests\Core\Plugin\Context;
 
-use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
 use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface;
 use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionTrait;
 use Drupal\Component\Plugin\Definition\PluginDefinition;
@@ -19,6 +18,7 @@
  * @coversDefaultClass \Drupal\Core\Plugin\ContextAwarePluginBase
  *
  * @group Plugin
+ * @group legacy
  */
 class ContextAwarePluginBaseTest extends KernelTestBase {
 
@@ -41,7 +41,10 @@ public function setUp(): void {
     ];
     $plugin_definition = new TestPluginDefinition();
     $plugin_definition->addContextDefinition('nato_letter', ContextDefinition::create('string'));
-    $this->plugin = new TestContextAwarePlugin($configuration, 'the_sisko', $plugin_definition);
+    $this->plugin = $this->getMockBuilder(ContextAwarePluginBase::class)
+      ->setConstructorArgs([$configuration, 'the_sisko', $plugin_definition])
+      ->setMethods(['setContext'])
+      ->getMockForAbstractClass();
   }
 
   /**
@@ -81,9 +84,8 @@ public function testSetContextValue() {
 
     $this->plugin->getPluginDefinition()->addContextDefinition('foo', new ContextDefinition('string'));
 
-    $this->assertFalse($this->plugin->setContextCalled);
+    $this->plugin->expects($this->exactly(1))->method('setContext');
     $this->plugin->setContextValue('foo', new StringData(new DataDefinition(), 'bar'));
-    $this->assertTrue($this->plugin->setContextCalled);
   }
 
 }
@@ -93,22 +95,3 @@ class TestPluginDefinition extends PluginDefinition implements ContextAwarePlugi
   use ContextAwarePluginDefinitionTrait;
 
 }
-
-class TestContextAwarePlugin extends ContextAwarePluginBase {
-
-  /**
-   * Indicates if ::setContext() has been called or not.
-   *
-   * @var bool
-   */
-  public $setContextCalled = FALSE;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setContext($name, ComponentContextInterface $context) {
-    parent::setContext($name, $context);
-    $this->setContextCalled = TRUE;
-  }
-
-}
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginTraitTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginTraitTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..b5a7aeb2e7ffbce0aa558d051ba55e6e1b7ed20a
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/Context/ContextAwarePluginTraitTest.php
@@ -0,0 +1,184 @@
+<?php
+
+namespace Drupal\KernelTests\Core\Plugin\Context;
+
+use Drupal\Component\Plugin\ConfigurableInterface;
+use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface;
+use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface;
+use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionTrait;
+use Drupal\Component\Plugin\Definition\PluginDefinition;
+use Drupal\Component\Plugin\Exception\ContextException;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\Plugin\DataType\StringData;
+use Drupal\Core\TypedData\TypedDataManagerInterface;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\Traits\ExpectDeprecationTrait;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Plugin\ContextAwarePluginTrait
+ *
+ * @group Plugin
+ */
+class ContextAwarePluginTraitTest extends KernelTestBase {
+
+  use ExpectDeprecationTrait;
+
+  /**
+   * The plugin instance under test.
+   *
+   * @var \Drupal\Core\Plugin\ContextAwarePluginTrait
+   */
+  private $plugin;
+
+  /**
+   * The configurable plugin instance under test.
+   *
+   * @var \Drupal\Core\Plugin\ContextAwarePluginTrait
+   */
+  private $configurablePlugin;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(): void {
+    parent::setUp();
+    $plugin_definition = new TestContextAwarePluginDefinition();
+    $plugin_definition->addContextDefinition('nato_letter', ContextDefinition::create('string'));
+    $this->plugin = new TestContextAwarePlugin([], 'the_sisko', $plugin_definition);
+    $this->configurablePlugin = new TestConfigurableContextAwarePlugin([], 'the_sisko', $plugin_definition);
+  }
+
+  /**
+   * @covers ::getContextDefinitions
+   */
+  public function testGetContextDefinitions() {
+    $this->assertIsArray($this->plugin->getContextDefinitions());
+  }
+
+  /**
+   * @covers ::getContextDefinition
+   */
+  public function testGetContextDefinition() {
+    // The context is not defined, so an exception will be thrown.
+    $this->expectException(ContextException::class);
+    $this->expectExceptionMessage('The person context is not a valid context.');
+    $this->plugin->getContextDefinition('person');
+  }
+
+  /**
+   * @covers ::getContextValue
+   */
+  public function testGetContextValue() {
+    $this->plugin->setContextValue('nato_letter', 'Alpha');
+    $this->assertSame('Alpha', $this->plugin->getContextValue('nato_letter'));
+  }
+
+  /**
+   * @covers ::getContextValue
+   * @group legacy
+   */
+  public function testGetContextValueFromConfiguration() {
+    $this->expectDeprecation('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980');
+    $configuration = [
+      'context' => [
+        'nato_letter' => 'Alpha',
+      ],
+    ];
+    $this->plugin = new TestContextAwarePlugin($configuration, 'the_sisko', $this->plugin->getPluginDefinition());
+    // Assert that the context value passed in the plugin configuration is
+    // available.
+    $this->assertSame('Alpha', $this->plugin->getContextValue('nato_letter'));
+  }
+
+  /**
+   * @covers ::getContextValue
+   * @group legacy
+   */
+  public function testConfigurableGetContextValueFromConfiguration() {
+    $this->expectDeprecation('Passing context values to plugins via configuration is deprecated in drupal:9.1.0 and will be removed before drupal:10.0.0. Instead, call ::setContextValue() on the plugin itself. See https://www.drupal.org/node/3120980');
+    // Assert that the context value passed in the plugin configuration is
+    // available.
+    $this->assertSame('Alpha', $this->configurablePlugin->getContextValue('nato_letter'));
+  }
+
+  /**
+   * @covers ::setContextValue
+   */
+  public function testSetContextValue() {
+    $typed_data_manager = $this->prophesize(TypedDataManagerInterface::class);
+    $container = new ContainerBuilder();
+    $container->set('typed_data_manager', $typed_data_manager->reveal());
+    \Drupal::setContainer($container);
+
+    $this->plugin->getPluginDefinition()->addContextDefinition('foo', new ContextDefinition('string'));
+
+    $this->assertFalse($this->plugin->setContextCalled);
+    $this->plugin->setContextValue('foo', new StringData(new DataDefinition(), 'bar'));
+    $this->assertTrue($this->plugin->setContextCalled);
+  }
+
+}
+
+class TestContextAwarePluginDefinition extends PluginDefinition implements ContextAwarePluginDefinitionInterface {
+
+  use ContextAwarePluginDefinitionTrait;
+
+}
+
+class TestContextAwarePlugin extends PluginBase implements ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait {
+    setContext as setContextTrait;
+  }
+
+  /**
+   * Indicates if ::setContext() has been called or not.
+   *
+   * @var bool
+   */
+  public $setContextCalled = FALSE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setContext($name, ComponentContextInterface $context) {
+    $this->setContextTrait($name, $context);
+    $this->setContextCalled = TRUE;
+  }
+
+}
+
+class TestConfigurableContextAwarePlugin extends PluginBase implements ConfigurableInterface, ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfiguration() {
+    return [
+      'context' => [
+        'nato_letter' => 'Alpha',
+      ],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setConfiguration(array $configuration) {
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/ContextHandlerTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/ContextHandlerTest.php
index a3a43d871c185e70269df03fe21d4a5b40b4fa0c..089731ea052bfa6c2a28994e64aebc490a998b07 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/ContextHandlerTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/ContextHandlerTest.php
@@ -5,7 +5,9 @@
 use Drupal\Core\Plugin\Context\ContextHandler;
 use Drupal\Core\Plugin\Context\EntityContext;
 use Drupal\Core\Plugin\Context\EntityContextDefinition;
-use Drupal\Core\Plugin\ContextAwarePluginBase;
+use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\ContextAwarePluginTrait;
+use Drupal\Core\Plugin\PluginBase;
 use Drupal\entity_test\Entity\EntityTest;
 use Drupal\KernelTests\KernelTestBase;
 
@@ -66,6 +68,8 @@ public function testApplyContextMappingAlreadyApplied() {
 /**
  * Provides a test implementation of a context-aware plugin.
  */
-class TestContextAwarePlugin extends ContextAwarePluginBase {
+class TestContextAwarePlugin extends PluginBase implements ContextAwarePluginInterface {
+
+  use ContextAwarePluginTrait;
 
 }