diff --git a/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php
new file mode 100644
index 0000000..3c500ea
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/ConfigurablePluginInterface.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\ConfigurablePluginInterface.
+ */
+
+namespace Drupal\Component\Plugin;
+
+/**
+ * Provides an interface for a configurable plugin.
+ */
+interface ConfigurablePluginInterface {
+
+  /**
+   * Returns this plugin's configuration.
+   *
+   * @return array
+   *   An array of this plugin's configuration.
+   */
+  public function getConfiguration();
+
+  /**
+   * Sets the configuration for this plugin instance.
+   *
+   * @param array $configuration
+   *   An associative array containing the plugin's configuration.
+   */
+  public function setConfiguration(array $configuration);
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/DefaultPluginBag.php b/core/lib/Drupal/Component/Plugin/DefaultPluginBag.php
new file mode 100644
index 0000000..60af300
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/DefaultPluginBag.php
@@ -0,0 +1,138 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\DefaultPluginBag.
+ */
+
+namespace Drupal\Component\Plugin;
+
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Utility\MapArray;
+use Drupal\Component\Utility\String;
+
+/**
+ * Provides a default plugin bag for a plugin type.
+ *
+ * A plugin bag is used to contain plugins that will be lazily instantiated. The
+ * configurations of each potential plugin are passed in, and the configuration
+ * key containing the plugin ID is specified by self::$pluginKey.
+ */
+class DefaultPluginBag extends PluginBag {
+
+  /**
+   * The manager used to instantiate the plugins.
+   *
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  protected $manager;
+
+  /**
+   * The initial configuration for each plugin in the bag.
+   *
+   * @var array
+   *   An associative array containing the initial configuration for each plugin
+   *   in the bag, keyed by plugin instance ID.
+   */
+  protected $configurations = array();
+
+  /**
+   * The key within the plugin configuration that contains the plugin ID.
+   *
+   * @var string
+   */
+  protected $pluginKey = 'plugin';
+
+  /**
+   * Constructs a new DefaultPluginBag object.
+   *
+   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
+   *   The manager to be used for instantiating plugins.
+   * @param array $configurations
+   *   (optional) An associative array containing the initial configuration for
+   *   each plugin in the bag, keyed by plugin instance ID.
+   */
+  public function __construct(PluginManagerInterface $manager, array $configurations = array()) {
+    $this->manager = $manager;
+    $this->configurations = $configurations;
+
+    if (!empty($configurations)) {
+      $this->instanceIDs = MapArray::copyValuesToKeys(array_keys($configurations));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function initializePlugin($instance_id) {
+    if (!isset($this->pluginInstances[$instance_id])) {
+      $configuration = $this->configurations[$instance_id];
+      if (!isset($configuration[$this->pluginKey])) {
+        throw new PluginException(String::format("Unknown plugin ID '@instance'.", array('@instance' => $instance_id)));
+      }
+      $this->pluginInstances[$instance_id] = $this->manager->createInstance($configuration[$this->pluginKey], $configuration);
+      $this->addInstanceID($instance_id);
+    }
+  }
+
+  /**
+   * Sorts all plugin instances in this bag.
+   *
+   * @return self
+   *   Returns the plugin bag.
+   */
+  public function sort() {
+    uasort($this->instanceIDs, array($this, 'sortHelper'));
+    return $this;
+  }
+
+  /**
+   * Provides uasort() callback to sort plugins.
+   */
+  public function sortHelper($aID, $bID) {
+    $a = $this->get($aID);
+    $b = $this->get($bID);
+    return strnatcasecmp($a->getPluginId(), $b->getPluginId());
+  }
+
+  /**
+   * Returns the current configuration of all plugins in this bag.
+   *
+   * @return array
+   *   An associative array keyed by instance ID, whose values are up-to-date
+   *   plugin configurations.
+   */
+  public function getConfiguration() {
+    $instances = array();
+    $this->rewind();
+    foreach ($this as $instance_id => $instance) {
+      if ($instance instanceof ConfigurablePluginInterface) {
+        $instances[$instance_id] = $instance->getConfiguration();
+      }
+      else {
+        $instances[$instance_id] = $this->configurations[$instance_id];
+      }
+    }
+    return $instances;
+  }
+
+  /**
+   * Updates the configuration for a plugin instance.
+   *
+   * If there is no plugin instance yet, a new will be instantiated. Otherwise,
+   * the existing instance is updated with the new configuration.
+   *
+   * @param string $instance_id
+   *   The ID of a plugin to set the configuration for.
+   * @param array $configuration
+   *   The plugin configuration to set.
+   */
+  public function setConfiguration($instance_id, array $configuration) {
+    $this->configurations[$instance_id] = $configuration;
+    $instance = $this->get($instance_id);
+    if ($instance instanceof ConfigurablePluginInterface) {
+      $instance->setConfiguration($configuration);
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/DefaultSinglePluginBag.php b/core/lib/Drupal/Component/Plugin/DefaultSinglePluginBag.php
new file mode 100644
index 0000000..023ba3e
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/DefaultSinglePluginBag.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Plugin\DefaultSinglePluginBag.
+ */
+
+namespace Drupal\Component\Plugin;
+
+use Drupal\Component\Utility\MapArray;
+
+/**
+ * Provides a default plugin bag for a plugin type.
+ *
+ * A plugin bag usually stores multiple plugins, and is used to lazily
+ * instantiate them. When only one plugin is needed, it is still best practice
+ * to encapsulate all of the instantiation logic in a plugin bag. This class can
+ * be used directly, or subclassed to add further exception handling in
+ * self::initializePlugin().
+ */
+class DefaultSinglePluginBag extends PluginBag {
+
+  /**
+   * The manager used to instantiate the plugins.
+   *
+   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  protected $manager;
+
+  /**
+   * An array of configuration to instantiate the plugin with.
+   *
+   * @var array
+   */
+  protected $configuration;
+
+  /**
+   * Constructs a new DefaultSinglePluginBag object.
+   *
+   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
+   *   The manager to be used for instantiating plugins.
+   * @param array $instance_ids
+   *   The IDs of the plugin instances with which we are dealing.
+   * @param array $configuration
+   *   An array of configuration.
+   */
+  public function __construct(PluginManagerInterface $manager, array $instance_ids, array $configuration) {
+    $this->manager = $manager;
+    $this->instanceIDs = MapArray::copyValuesToKeys($instance_ids);
+    $this->configuration = $configuration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function initializePlugin($instance_id) {
+    if (!isset($this->pluginInstances[$instance_id])) {
+      $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $this->configuration);
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Action/ActionBag.php b/core/lib/Drupal/Core/Action/ActionBag.php
index a8210fe..de0e1d7 100644
--- a/core/lib/Drupal/Core/Action/ActionBag.php
+++ b/core/lib/Drupal/Core/Action/ActionBag.php
@@ -7,46 +7,11 @@
 
 namespace Drupal\Core\Action;
 
-use Drupal\Component\Plugin\PluginBag;
-use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Component\Plugin\DefaultSinglePluginBag;
 
 /**
  * Provides a container for lazily loading Action plugins.
  */
-class ActionBag extends PluginBag {
-
-  /**
-   * The manager used to instantiate the plugins.
-   *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
-   */
-  protected $manager;
-
-  /**
-   * Constructs a new ActionBag object.
-   *
-   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
-   *   The manager to be used for instantiating plugins.
-   * @param array $instance_ids
-   *   The ids of the plugin instances with which we are dealing.
-   * @param array $configuration
-   *   An array of configuration.
-   */
-  public function __construct(PluginManagerInterface $manager, array $instance_ids, array $configuration) {
-    $this->manager = $manager;
-    $this->instanceIDs = drupal_map_assoc($instance_ids);
-    $this->configuration = $configuration;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function initializePlugin($instance_id) {
-    if (isset($this->pluginInstances[$instance_id])) {
-      return;
-    }
-
-    $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $this->configuration);
-  }
+class ActionBag extends DefaultSinglePluginBag {
 
 }
diff --git a/core/lib/Drupal/Core/Action/ConfigurableActionBase.php b/core/lib/Drupal/Core/Action/ConfigurableActionBase.php
index 04ca4fe..25fe32f 100644
--- a/core/lib/Drupal/Core/Action/ConfigurableActionBase.php
+++ b/core/lib/Drupal/Core/Action/ConfigurableActionBase.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\Core\Action;
 
-use Drupal\Core\Action\ConfigurableActionInterface;
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
 use Drupal\Core\Action\ActionBase;
+use Drupal\Core\Plugin\PluginFormInterface;
 
 /**
  * Provides a base implementation for a configurable Action plugin.
  */
-abstract class ConfigurableActionBase extends ActionBase implements ConfigurableActionInterface {
+abstract class ConfigurableActionBase extends ActionBase implements ConfigurablePluginInterface, PluginFormInterface {
 
   /**
    * {@inheritdoc}
@@ -43,7 +44,14 @@ public function getConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function validate(array &$form, array &$form_state) {
+  public function setConfiguration(array $configuration) {
+    $this->configuration = $configuration;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateConfigurationForm(array &$form, array &$form_state) {
   }
 
 }
diff --git a/core/lib/Drupal/Core/Action/ConfigurableActionInterface.php b/core/lib/Drupal/Core/Plugin/PluginFormInterface.php
similarity index 54%
rename from core/lib/Drupal/Core/Action/ConfigurableActionInterface.php
rename to core/lib/Drupal/Core/Plugin/PluginFormInterface.php
index c0a66a9..e029bba 100644
--- a/core/lib/Drupal/Core/Action/ConfigurableActionInterface.php
+++ b/core/lib/Drupal/Core/Plugin/PluginFormInterface.php
@@ -2,28 +2,15 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Action\ConfigurableActionInterface.
+ * Contains \Drupal\Core\Plugin\PluginFormInterface.
  */
 
-namespace Drupal\Core\Action;
-
-use Drupal\Core\Action\ActionInterface;
+namespace Drupal\Core\Plugin;
 
 /**
- * Provides an interface for an Action plugin.
- *
- * @see \Drupal\Core\Annotation\Operation
- * @see \Drupal\Core\Action\OperationManager
+ * Provides an interface for a plugin that contains a form.
  */
-interface ConfigurableActionInterface extends ActionInterface {
-
-  /**
-   * Returns this plugin's configuration.
-   *
-   * @return array
-   *   An array of this action plugin's configuration.
-   */
-  public function getConfiguration();
+interface PluginFormInterface {
 
   /**
    * Form constructor.
@@ -36,7 +23,7 @@ public function getConfiguration();
    * @return array
    *   The form structure.
    */
-  public function form(array $form, array &$form_state);
+  public function buildConfigurationForm(array $form, array &$form_state);
 
   /**
    * Form validation handler.
@@ -46,16 +33,21 @@ public function form(array $form, array &$form_state);
    * @param array $form_state
    *   An associative array containing the current state of the form.
    */
-  public function validate(array &$form, array &$form_state);
+  public function validateConfigurationForm(array &$form, array &$form_state);
 
   /**
    * Form submission handler.
    *
+   * To properly store submitted form values store them in $this->configuration.
+   * @code
+   *   $this->configuration['some_value'] = $form_state['values']['some_value'];
+   * @endcode
+   *
    * @param array $form
    *   An associative array containing the structure of the form.
    * @param array $form_state
    *   An associative array containing the current state of the form.
    */
-  public function submit(array &$form, array &$form_state);
+  public function submitConfigurationForm(array &$form, array &$form_state);
 
 }
diff --git a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php
index ff48164..e9df397 100644
--- a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php
+++ b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php
@@ -10,8 +10,8 @@
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityFormController;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Action\ConfigurableActionInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -97,8 +97,8 @@ public function form(array $form, array &$form_state) {
       '#value' => $this->entity->getType(),
     );
 
-    if ($this->plugin instanceof ConfigurableActionInterface) {
-      $form += $this->plugin->form($form, $form_state);
+    if ($this->plugin instanceof PluginFormInterface) {
+      $form += $this->plugin->buildConfigurationForm($form, $form_state);
     }
 
     return parent::form($form, $form_state);
@@ -133,8 +133,8 @@ protected function actions(array $form, array &$form_state) {
   public function validate(array $form, array &$form_state) {
     parent::validate($form, $form_state);
 
-    if ($this->plugin instanceof ConfigurableActionInterface) {
-      $this->plugin->validate($form, $form_state);
+    if ($this->plugin instanceof PluginFormInterface) {
+      $this->plugin->validateConfigurationForm($form, $form_state);
     }
   }
 
@@ -144,8 +144,8 @@ public function validate(array $form, array &$form_state) {
   public function submit(array $form, array &$form_state) {
     parent::submit($form, $form_state);
 
-    if ($this->plugin instanceof ConfigurableActionInterface) {
-      $this->plugin->submit($form, $form_state);
+    if ($this->plugin instanceof PluginFormInterface) {
+      $this->plugin->submitConfigurationForm($form, $form_state);
     }
     return $this->entity;
   }
diff --git a/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php b/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php
index d0244b1..d825415 100644
--- a/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php
+++ b/core/modules/action/lib/Drupal/action/Form/ActionAdminManageForm.php
@@ -57,7 +57,7 @@ public function getFormID() {
   public function buildForm(array $form, array &$form_state) {
     $actions = array();
     foreach ($this->manager->getDefinitions() as $id => $definition) {
-      if (is_subclass_of($definition['class'], '\Drupal\Core\Action\ConfigurableActionInterface')) {
+      if (is_subclass_of($definition['class'], '\Drupal\Core\Plugin\PluginFormInterface')) {
         $key = Crypt::hashBase64($id);
         $actions[$key] = $definition['label'] . '...';
       }
diff --git a/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php b/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php
index 43908b0..77e5f21 100644
--- a/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php
+++ b/core/modules/action/lib/Drupal/action/Plugin/Action/EmailAction.php
@@ -116,7 +116,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $form['recipient'] = array(
       '#type' => 'textfield',
       '#title' => t('Recipient'),
@@ -145,7 +145,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function validate(array &$form, array &$form_state) {
+  public function validateConfigurationForm(array &$form, array &$form_state) {
     if (!valid_email_address($form_state['values']['recipient']) && strpos($form_state['values']['recipient'], ':mail') === FALSE) {
       // We want the literal %author placeholder to be emphasized in the error message.
       form_set_error('recipient', t('Enter a valid email address or use a token e-mail address such as %author.', array('%author' => '[node:author:mail]')));
@@ -155,7 +155,7 @@ public function validate(array &$form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['recipient'] = $form_state['values']['recipient'];
     $this->configuration['subject'] = $form_state['values']['subject'];
     $this->configuration['message'] = $form_state['values']['message'];
diff --git a/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php b/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php
index 93a4c87..fd158fb 100644
--- a/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php
+++ b/core/modules/action/lib/Drupal/action/Plugin/Action/GotoAction.php
@@ -96,7 +96,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $form['url'] = array(
       '#type' => 'textfield',
       '#title' => t('URL'),
@@ -110,7 +110,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['url'] = $form_state['values']['url'];
   }
 
diff --git a/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php b/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php
index b7f25a2..fef9ab9 100644
--- a/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php
+++ b/core/modules/action/lib/Drupal/action/Plugin/Action/MessageAction.php
@@ -70,7 +70,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $form['message'] = array(
       '#type' => 'textarea',
       '#title' => t('Message'),
@@ -85,7 +85,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['message'] = $form_state['values']['message'];
     unset($this->configuration['node']);
   }
diff --git a/core/modules/block/lib/Drupal/block/BlockBase.php b/core/modules/block/lib/Drupal/block/BlockBase.php
index b438dc1..947439e 100644
--- a/core/modules/block/lib/Drupal/block/BlockBase.php
+++ b/core/modules/block/lib/Drupal/block/BlockBase.php
@@ -50,50 +50,28 @@ public function settings() {
   }
 
   /**
-   * Returns the configuration data for the block plugin.
-   *
-   * @return array
-   *   The plugin configuration array from PluginBase::$configuration.
-   *
-   * @todo This doesn't belong here. Move this into a new base class in
-   *   http://drupal.org/node/1764380.
-   * @todo This does not return a config object, so the name is confusing.
-   *
-   * @see \Drupal\Component\Plugin\PluginBase::$configuration
+   * {@inheritdoc}
    */
-  public function getConfig() {
+  public function getConfiguration() {
     return $this->configuration;
   }
 
   /**
-   * Sets a particular value in the block settings.
-   *
-   * @param string $key
-   *   The key of PluginBase::$configuration to set.
-   * @param mixed $value
-   *   The value to set for the provided key.
-   *
-   * @todo This doesn't belong here. Move this into a new base class in
-   *   http://drupal.org/node/1764380.
-   * @todo This does not set a value in config(), so the name is confusing.
-   *
-   * @see \Drupal\Component\Plugin\PluginBase::$configuration
+   * {@inheritdoc}
+   */
+  public function setConfiguration(array $configuration) {
+    $this->configuration = $configuration;
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function setConfig($key, $value) {
     $this->configuration[$key] = $value;
   }
 
   /**
-   * Indicates whether block-specific criteria allow access to the block.
-   *
-   * Blocks with access restrictions that should always be applied,
-   * regardless of user-configured settings, should implement this method
-   * with that access control logic.
-   *
-   * @return bool
-   *   FALSE to deny access to the block, or TRUE to allow access.
-   *
-   * @see hook_block_access()
+   * {@inheritdoc}
    */
   public function access() {
     // By default, the block is visible unless user-configured rules indicate
@@ -102,7 +80,7 @@ public function access() {
   }
 
   /**
-   * Implements \Drupal\block\BlockPluginInterface::form().
+   * {@inheritdoc}
    *
    * Creates a generic configuration form for all block types. Individual
    * block plugins can add elements to this form by overriding
@@ -111,7 +89,7 @@ public function access() {
    *
    * @see \Drupal\block\BlockBase::blockForm()
    */
-  public function form($form, &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $definition = $this->getPluginDefinition();
     $form['module'] = array(
       '#type' => 'value',
@@ -138,27 +116,14 @@ public function form($form, &$form_state) {
   }
 
   /**
-   * Returns the configuration form elements specific to this block plugin.
-   *
-   * Blocks that need to add form elements to the normal block configuration
-   * form should implement this method.
-   *
-   * @param array $form
-   *   The form definition array for the block configuration form.
-   * @param array $form_state
-   *   An array containing the current state of the configuration form.
-   *
-   * @return array $form
-   *   The renderable form array representing the entire configuration form.
-   *
-   * @see \Drupal\block\BlockBase::form()
+   * {@inheritdoc}
    */
   public function blockForm($form, &$form_state) {
     return array();
   }
 
   /**
-   * Implements \Drupal\block\BlockPluginInterface::validate().
+   * {@inheritdoc}
    *
    * Most block plugins should not override this method. To add validation
    * for a specific block type, override BlockBase::blockValdiate().
@@ -167,30 +132,17 @@ public function blockForm($form, &$form_state) {
    *
    * @see \Drupal\block\BlockBase::blockValidate()
    */
-  public function validate($form, &$form_state) {
+  public function validateConfigurationForm(array &$form, array &$form_state) {
     $this->blockValidate($form, $form_state);
   }
 
   /**
-   * Adds block type-specific validation for the block form.
-   *
-   * Note that this method takes the form structure and form state arrays for
-   * the full block configuration form as arguments, not just the elements
-   * defined in BlockBase::blockForm().
-   *
-   * @param array $form
-   *   The form definition array for the full block configuration form.
-   * @param array $form_state
-   *   An array containing the current state of the configuration form.
-   *
-   * @see \Drupal\block\BlockBase::blockForm()
-   * @see \Drupal\block\BlockBase::blockSubmit()
-   * @see \Drupal\block\BlockBase::validate()
+   * {@inheritdoc}
    */
   public function blockValidate($form, &$form_state) {}
 
   /**
-   * Implements \Drupal\block\BlockPluginInterface::submit().
+   * {@inheritdoc}
    *
    * Most block plugins should not override this method. To add submission
    * handling for a specific block type, override BlockBase::blockSubmit().
@@ -199,7 +151,7 @@ public function blockValidate($form, &$form_state) {}
    *
    * @see \Drupal\block\BlockBase::blockSubmit()
    */
-  public function submit($form, &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     if (!form_get_errors()) {
       $this->configuration['label'] = $form_state['values']['label'];
       $this->configuration['label_display'] = $form_state['values']['label_display'];
@@ -209,20 +161,8 @@ public function submit($form, &$form_state) {
   }
 
   /**
-   * Adds block type-specific submission handling for the block form.
-   *
-   * Note that this method takes the form structure and form state arrays for
-   * the full block configuration form as arguments, not just the elements
-   * defined in BlockBase::blockForm().
-   *
-   * @param array $form
-   *   The form definition array for the full block configuration form.
-   * @param array $form_state
-   *   An array containing the current state of the configuration form.
-   *
-   * @see \Drupal\block\BlockBase::blockForm()
-   * @see \Drupal\block\BlockBase::blockValidate()
-   * @see \Drupal\block\BlockBase::submit()
+   * {@inheritdoc}
    */
   public function blockSubmit($form, &$form_state) {}
+
 }
diff --git a/core/modules/block/lib/Drupal/block/BlockFormController.php b/core/modules/block/lib/Drupal/block/BlockFormController.php
index f562a68..7789c02 100644
--- a/core/modules/block/lib/Drupal/block/BlockFormController.php
+++ b/core/modules/block/lib/Drupal/block/BlockFormController.php
@@ -25,7 +25,7 @@ public function form(array $form, array &$form_state) {
       '#type' => 'value',
       '#value' => $entity->id(),
     );
-    $form['settings'] = $entity->getPlugin()->form(array(), $form_state);
+    $form['settings'] = $entity->getPlugin()->buildConfigurationForm(array(), $form_state);
 
     $form['machine_name'] = array(
       '#type' => 'machine_name',
@@ -208,7 +208,7 @@ public function validate(array $form, array &$form_state) {
       'values' => &$form_state['values']['settings']
     );
     // Call the plugin validate handler.
-    $entity->getPlugin()->validate($form, $settings);
+    $entity->getPlugin()->validateConfigurationForm($form, $settings);
   }
 
   /**
@@ -224,7 +224,7 @@ public function submit(array $form, array &$form_state) {
       'values' => &$form_state['values']['settings']
     );
     // Call the plugin submit handler.
-    $entity->getPlugin()->submit($form, $settings);
+    $entity->getPlugin()->submitConfigurationForm($form, $settings);
 
     // Save the settings of the plugin.
     $entity->save();
diff --git a/core/modules/block/lib/Drupal/block/BlockPluginBag.php b/core/modules/block/lib/Drupal/block/BlockPluginBag.php
index 5a68beb..7807034 100644
--- a/core/modules/block/lib/Drupal/block/BlockPluginBag.php
+++ b/core/modules/block/lib/Drupal/block/BlockPluginBag.php
@@ -7,38 +7,30 @@
 
 namespace Drupal\block;
 
-use Drupal\block\Plugin\Core\Entity\Block;
-use Drupal\Component\Plugin\PluginBag;
-use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Component\Utility\String;
+use Drupal\Component\Plugin\DefaultSinglePluginBag;
 
 /**
  * Provides a collection of block plugins.
  */
-class BlockPluginBag extends PluginBag {
+class BlockPluginBag extends DefaultSinglePluginBag {
 
   /**
-   * The manager used to instantiate the plugins.
+   * The block ID this plugin bag belongs to.
    *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   * @var string
    */
-  protected $manager;
+  protected $blockId;
 
   /**
-   * Constructs a BlockPluginBag object.
-   *
-   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
-   *   The manager to be used for instantiating plugins.
-   * @param array $instance_ids
-   *   The ids of the plugin instances with which we are dealing.
-   * @param \Drupal\block\Plugin\Core\Entity\Block $entity
-   *   The Block entity that holds our configuration.
+   * {@inheritdoc}
    */
-  public function __construct(PluginManagerInterface $manager, array $instance_ids, Block $entity) {
-    $this->manager = $manager;
-    $this->entity = $entity;
+  public function __construct(PluginManagerInterface $manager, array $instance_ids, array $configuration, $block_id) {
+    parent::__construct($manager, $instance_ids, $configuration);
 
-    $this->instanceIDs = drupal_map_assoc($instance_ids);
+    $this->blockId = $block_id;
   }
 
   /**
@@ -46,18 +38,14 @@ public function __construct(PluginManagerInterface $manager, array $instance_ids
    */
   protected function initializePlugin($instance_id) {
     if (!$instance_id) {
-      throw new PluginException(format_string("The block '@block' did not specify a plugin.", array('@block' => $this->entity->id())));
-    }
-    if (isset($this->pluginInstances[$instance_id])) {
-      return;
+      throw new PluginException(String::format("The block '@block' did not specify a plugin.", array('@block' => $this->blockId)));
     }
 
-    $settings = $this->entity->get('settings');
     try {
-      $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $settings);
+      parent::initializePlugin($instance_id);
     }
     catch (PluginException $e) {
-      $module = $settings['module'];
+      $module = $this->configuration['module'];
       // Ignore blocks belonging to disabled modules, but re-throw valid
       // exceptions when the module is enabled and the plugin is misconfigured.
       if (!$module || \Drupal::moduleHandler()->moduleExists($module)) {
diff --git a/core/modules/block/lib/Drupal/block/BlockPluginInterface.php b/core/modules/block/lib/Drupal/block/BlockPluginInterface.php
index 1887816..86a7644 100644
--- a/core/modules/block/lib/Drupal/block/BlockPluginInterface.php
+++ b/core/modules/block/lib/Drupal/block/BlockPluginInterface.php
@@ -7,6 +7,10 @@
 
 namespace Drupal\block;
 
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
+
 /**
  * Defines the required interface for all block plugins.
  *
@@ -14,10 +18,8 @@
  *   architecture and the relationships between the various objects, including
  *   brif references to the important components that are not coupled to the
  *   interface.
- *
- * @see \Drupal\block\BlockBase
  */
-interface BlockPluginInterface {
+interface BlockPluginInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface {
 
   /**
    * Returns the default settings for this block plugin.
@@ -45,61 +47,79 @@ public function settings();
   public function access();
 
   /**
-   * Constructs the block configuration form.
+   * Builds and returns the renderable array for this block plugin.
    *
-   * This method allows base implementations to add a generic configuration
-   * form for extending block plugins.
+   * @return array
+   *   A renderable array representing the content of the block.
    *
-   * @param array $form
-   *   The form definition array for the block configuration form.
-   * @param array $form_state
-   *   An array containing the current state of the configuration form.
+   * @see \Drupal\block\BlockRenderController
+   */
+  public function build();
+
+  /**
+   * Sets a particular value in the block settings.
    *
-   * @return array $form
-   *   The renderable form array representing the entire configuration form.
+   * @param string $key
+   *   The key of PluginBase::$configuration to set.
+   * @param mixed $value
+   *   The value to set for the provided key.
    *
-   * @see \Drupal\block\BlockFormController::form()
-   * @see \Drupal\block\BlockInterace::validate()
-   * @see \Drupal\block\BlockInterace::submit()
+   * @todo This doesn't belong here. Move this into a new base class in
+   *   http://drupal.org/node/1764380.
+   * @todo This does not set a value in config(), so the name is confusing.
+   *
+   * @see \Drupal\Component\Plugin\PluginBase::$configuration
    */
-  public function form($form, &$form_state);
+  public function setConfig($key, $value);
 
   /**
-   * Handles form validation for the block configuration form.
+   * Returns the configuration form elements specific to this block plugin.
+   *
+   * Blocks that need to add form elements to the normal block configuration
+   * form should implement this method.
    *
    * @param array $form
    *   The form definition array for the block configuration form.
    * @param array $form_state
    *   An array containing the current state of the configuration form.
    *
-   * @see \Drupal\block\BlockFormController::validate()
-   * @see \Drupal\block\BlockInterace::form()
-   * @see \Drupal\block\BlockInterace::submit()
+   * @return array $form
+   *   The renderable form array representing the entire configuration form.
    */
-  public function validate($form, &$form_state);
+  public function blockForm($form, &$form_state);
 
   /**
-   * Handles form submissions for the block configuration form.
+   * Adds block type-specific validation for the block form.
+   *
+   * Note that this method takes the form structure and form state arrays for
+   * the full block configuration form as arguments, not just the elements
+   * defined in BlockPluginInterface::blockForm().
    *
    * @param array $form
-   *   The form definition array for the block configuration form.
+   *   The form definition array for the full block configuration form.
    * @param array $form_state
    *   An array containing the current state of the configuration form.
    *
-   * @see \Drupal\block\BlockFormController::submit()
-   * @see \Drupal\block\BlockInterace::form()
-   * @see \Drupal\block\BlockInterace::validate()
+   * @see \Drupal\block\BlockPluginInterface::blockForm()
+   * @see \Drupal\block\BlockPluginInterface::blockSubmit()
    */
-  public function submit($form, &$form_state);
+  public function blockValidate($form, &$form_state);
 
   /**
-   * Builds and returns the renderable array for this block plugin.
+   * Adds block type-specific submission handling for the block form.
    *
-   * @return array
-   *   A renderable array representing the content of the block.
+   * Note that this method takes the form structure and form state arrays for
+   * the full block configuration form as arguments, not just the elements
+   * defined in BlockPluginInterface::blockForm().
    *
-   * @see \Drupal\block\BlockRenderController
+   * @param array $form
+   *   The form definition array for the full block configuration form.
+   * @param array $form_state
+   *   An array containing the current state of the configuration form.
+   *
+   * @see \Drupal\block\BlockPluginInterface::blockForm()
+   * @see \Drupal\block\BlockPluginInterface::blockValidate()
    */
-  public function build();
+  public function blockSubmit($form, &$form_state);
 
 }
diff --git a/core/modules/block/lib/Drupal/block/BlockRenderController.php b/core/modules/block/lib/Drupal/block/BlockRenderController.php
index 45a85d9..57a5d62 100644
--- a/core/modules/block/lib/Drupal/block/BlockRenderController.php
+++ b/core/modules/block/lib/Drupal/block/BlockRenderController.php
@@ -40,7 +40,7 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
       $plugin_id = $plugin->getPluginId();
 
       if ($content = $plugin->build()) {
-        $configuration = $plugin->getConfig();
+        $configuration = $plugin->getConfiguration();
         $build[$entity_id] = array(
           '#theme' => 'block',
           'content' => $content,
diff --git a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php
index 1d3cca8..bb3a1d4 100644
--- a/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php
+++ b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.php
@@ -105,7 +105,7 @@ class Block extends ConfigEntityBase implements BlockInterface {
   public function __construct(array $values, $entity_type) {
     parent::__construct($values, $entity_type);
 
-    $this->pluginBag = new BlockPluginBag(\Drupal::service('plugin.manager.block'), array($this->plugin), $this);
+    $this->pluginBag = new BlockPluginBag(\Drupal::service('plugin.manager.block'), array($this->plugin), $this->get('settings'), $this->id());
   }
 
   /**
@@ -169,7 +169,7 @@ public function getExportProperties() {
    * {@inheritdoc}
    */
   public function preSave(EntityStorageControllerInterface $storage_controller) {
-    $this->set('settings', $this->getPlugin()->getConfig());
+    $this->set('settings', $this->getPlugin()->getConfiguration());
   }
 
 }
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php
index 327cf45..b3093d9 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockInterfaceTest.php
@@ -52,12 +52,12 @@ public function testBlockInterface() {
     );
     // Initial configuration of the block at construction time.
     $display_block = $manager->createInstance('test_block_instantiation', $configuration);
-    $this->assertIdentical($display_block->getConfig(), $expected_configuration, 'The block was configured correctly.');
+    $this->assertIdentical($display_block->getConfiguration(), $expected_configuration, 'The block was configured correctly.');
 
     // Updating an element of the configuration.
     $display_block->setConfig('display_message', 'My custom display message.');
     $expected_configuration['display_message'] = 'My custom display message.';
-    $this->assertIdentical($display_block->getConfig(), $expected_configuration, 'The block configuration was updated correctly.');
+    $this->assertIdentical($display_block->getConfiguration(), $expected_configuration, 'The block configuration was updated correctly.');
 
     $expected_form = array(
       'module' => array(
@@ -85,7 +85,7 @@ public function testBlockInterface() {
     );
     $form_state = array();
     // Ensure there are no form elements that do not belong to the plugin.
-    $this->assertIdentical($display_block->form(array(), $form_state), $expected_form, 'Only the expected form elements were present.');
+    $this->assertIdentical($display_block->buildConfigurationForm(array(), $form_state), $expected_form, 'Only the expected form elements were present.');
 
     $expected_build = array(
       '#children' => 'My custom display message.',
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php
index 51630ba..3042b5b 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTemplateSuggestionsUnitTest.php
@@ -45,7 +45,7 @@ function testBlockThemeHookSuggestions() {
 
     $variables = array();
     $variables['elements']['#block'] = $block;
-    $variables['elements']['#configuration'] = $block->getPlugin()->getConfig();
+    $variables['elements']['#configuration'] = $block->getPlugin()->getConfiguration();
     $variables['elements']['#plugin_id'] = $block->get('plugin');
     $variables['elements']['content'] = array();
     // Test adding a class to the block content.
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php b/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php
index d123cfc..d669db4 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/Action/UnpublishByKeywordComment.php
@@ -49,7 +49,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $form['keywords'] = array(
       '#title' => t('Keywords'),
       '#type' => 'textarea',
@@ -62,7 +62,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['keywords'] = drupal_explode_tags($form_state['values']['keywords']);
   }
 
diff --git a/core/modules/filter/config/filter.format.plain_text.yml b/core/modules/filter/config/filter.format.plain_text.yml
index 586e28d..ea0a4bd 100644
--- a/core/modules/filter/config/filter.format.plain_text.yml
+++ b/core/modules/filter/config/filter.format.plain_text.yml
@@ -13,12 +13,14 @@ cache: '1'
 filters:
   # Escape all HTML.
   filter_html_escape:
+    id: filter_html_escape
     module: filter
     status: '1'
     weight: '-10'
     settings: {  }
   # Convert URLs into links.
   filter_url:
+    id: filter_url
     module: filter
     status: '1'
     weight: '0'
@@ -26,6 +28,7 @@ filters:
       filter_url_length: '72'
   # Convert linebreaks into paragraphs.
   filter_autop:
+    id: filter_autop
     module: filter
     status: '1'
     weight: '0'
diff --git a/core/modules/filter/lib/Drupal/filter/FilterBag.php b/core/modules/filter/lib/Drupal/filter/FilterBag.php
index 781cfda..8de6646 100644
--- a/core/modules/filter/lib/Drupal/filter/FilterBag.php
+++ b/core/modules/filter/lib/Drupal/filter/FilterBag.php
@@ -7,31 +7,14 @@
 
 namespace Drupal\filter;
 
-use Drupal\Component\Plugin\PluginBag;
-use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Component\Plugin\Exception\PluginException;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Plugin\DefaultPluginBag;
 
 /**
  * A collection of filters.
  */
-class FilterBag extends PluginBag {
-
-  /**
-   * The initial configuration for each filter in the bag.
-   *
-   * @var array
-   *   An associative array containing the initial configuration for each filter
-   *   in the bag, keyed by plugin instance ID.
-   */
-  protected $configurations = array();
-
-  /**
-   * The manager used to instantiate the plugins.
-   *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
-   */
-  protected $manager;
+class FilterBag extends DefaultPluginBag {
 
   /**
    * All possible filter plugin IDs.
@@ -41,22 +24,9 @@ class FilterBag extends PluginBag {
   protected $definitions;
 
   /**
-   * Constructs a FilterBag object.
-   *
-   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
-   *   The manager to be used for instantiating plugins.
-   * @param array $configurations
-   *   (optional) An associative array containing the initial configuration for
-   *   each filter in the bag, keyed by plugin instance ID.
+   * {@inheritdoc}
    */
-  public function __construct(PluginManagerInterface $manager, array $configurations = array()) {
-    $this->manager = $manager;
-    $this->configurations = $configurations;
-
-    if (!empty($configurations)) {
-      $this->instanceIDs = array_combine(array_keys($configurations), array_keys($configurations));
-    }
-  }
+  protected $pluginKey = 'id';
 
   /**
    * Retrieves filter definitions and creates an instance for each filter.
@@ -86,22 +56,6 @@ public function getAll() {
   }
 
   /**
-   * Updates the configuration for a filter plugin instance.
-   *
-   * If there is no plugin instance yet, a new will be instantiated. Otherwise,
-   * the existing instance is updated with the new configuration.
-   *
-   * @param string $instance_id
-   *   The ID of a filter plugin to set the configuration for.
-   * @param array $configuration
-   *   The filter plugin configuration to set.
-   */
-  public function setConfig($instance_id, array $configuration) {
-    $this->configurations[$instance_id] = $configuration;
-    $this->get($instance_id)->setPluginConfiguration($configuration);
-  }
-
-  /**
    * {@inheritdoc}
    */
   protected function initializePlugin($instance_id) {
@@ -115,7 +69,6 @@ protected function initializePlugin($instance_id) {
     $definition = $this->manager->getDefinition($instance_id);
 
     if (isset($definition)) {
-      $this->addInstanceID($instance_id);
       // $configuration is the whole filter plugin instance configuration, as
       // contained in the text format configuration. The default configuration
       // is the filter plugin definition.
@@ -126,7 +79,8 @@ protected function initializePlugin($instance_id) {
       if (isset($this->configurations[$instance_id])) {
         $configuration = NestedArray::mergeDeep($configuration, $this->configurations[$instance_id]);
       }
-      $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $configuration, $this);
+      $this->configurations[$instance_id] = $configuration;
+      parent::initializePlugin($instance_id);
     }
     else {
       throw new PluginException(format_string("Unknown filter plugin ID '@filter'.", array('@filter' => $instance_id)));
@@ -134,20 +88,15 @@ protected function initializePlugin($instance_id) {
   }
 
   /**
-   * Sorts all filter plugin instances in this bag.
-   *
-   * @return \Drupal\filter\FilterBag
+   * {@inheritdoc}
    */
   public function sort() {
     $this->getAll();
-    uasort($this->instanceIDs, array($this, 'sortHelper'));
-    return $this;
+    return parent::sort();
   }
 
   /**
-   * uasort() callback to sort filters by status, weight, module, and name.
-   *
-   * @see \Drupal\filter\FilterFormatStorageController::preSave()
+   * {@inheritdoc}
    */
   public function sortHelper($aID, $bID) {
     $a = $this->get($aID);
@@ -164,22 +113,4 @@ public function sortHelper($aID, $bID) {
     return strnatcasecmp($a->getPluginId(), $b->getPluginId());
   }
 
-  /**
-   * Returns the current configuration of all filters in this bag.
-   *
-   * @return array
-   *   An associative array keyed by filter plugin instance ID, whose values
-   *   are filter configurations.
-   *
-   * @see \Drupal\filter\Plugin\Filter\FilterInterface::export()
-   */
-  public function export() {
-    $filters = array();
-    $this->rewind();
-    foreach ($this as $instance_id => $instance) {
-      $filters[$instance_id] = $instance->export();
-    }
-    return $filters;
-  }
-
 }
diff --git a/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php b/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php
index b3cb277..3d9b649 100644
--- a/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php
+++ b/core/modules/filter/lib/Drupal/filter/FilterPluginManager.php
@@ -8,12 +8,12 @@
 namespace Drupal\filter;
 
 use Drupal\Component\Plugin\PluginManagerBase;
-use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
+use Drupal\Core\Plugin\Factory\ContainerFactory;
 
 /**
  * Manages text processing filters.
@@ -36,15 +36,8 @@ public function __construct(\Traversable $namespaces) {
     $cache_key = 'filter_plugins:' . language(Language::TYPE_INTERFACE)->id;
     $cache_tags = array('filter_formats' => TRUE);
     $this->discovery = new CacheDecorator($this->discovery, $cache_key, 'cache', CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
-  }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function createInstance($plugin_id, array $configuration = array(), FilterBag $filter_bag = NULL) {
-    $plugin_definition = $this->getDefinition($plugin_id);
-    $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
-    return new $plugin_class($configuration, $plugin_id, $plugin_definition, $filter_bag);
+    $this->factory = new ContainerFactory($this);
   }
 
 }
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php
index a853bb6..7541b53 100644
--- a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php
@@ -155,7 +155,7 @@ public function filters($instance_id = NULL) {
   public function setFilterConfig($instance_id, array $configuration) {
     $this->filters[$instance_id] = $configuration;
     if (isset($this->filterBag)) {
-      $this->filterBag->setConfig($instance_id, $configuration);
+      $this->filterBag->setConfiguration($instance_id, $configuration);
     }
     return $this;
   }
@@ -166,7 +166,7 @@ public function setFilterConfig($instance_id, array $configuration) {
   public function getExportProperties() {
     $properties = parent::getExportProperties();
     // Sort and export the configuration of all filters.
-    $properties['filters'] = $this->filters()->sort()->export();
+    $properties['filters'] = $this->filters()->sort()->getConfiguration();
 
     return $properties;
   }
@@ -212,7 +212,7 @@ public function preSave(EntityStorageControllerInterface $storage_controller) {
     // Determine whether the format can be cached.
     // @todo This is a derived/computed definition, not configuration.
     $this->cache = TRUE;
-    foreach ($this->filters() as $filter) {
+    foreach ($this->filters()->getAll() as $filter) {
       if ($filter->status && !$filter->cache) {
         $this->cache = FALSE;
       }
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php
index 2e80bd0..859ff50 100644
--- a/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterBase.php
@@ -70,21 +70,19 @@
   /**
    * {@inheritdoc}
    */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, FilterBag $bag) {
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     $this->module = $this->pluginDefinition['module'];
     $this->cache = $this->pluginDefinition['cache'];
 
-    $this->setPluginConfiguration($configuration);
-
-    $this->bag = $bag;
+    $this->setConfiguration($configuration);
   }
 
   /**
    * {@inheritdoc}
    */
-  public function setPluginConfiguration(array $configuration) {
+  public function setConfiguration(array $configuration) {
     if (isset($configuration['status'])) {
       $this->status = (bool) $configuration['status'];
     }
@@ -100,8 +98,9 @@ public function setPluginConfiguration(array $configuration) {
   /**
    * {@inheritdoc}
    */
-  public function export() {
+  public function getConfiguration() {
     return array(
+      'id' => $this->getPluginId(),
       'module' => $this->pluginDefinition['module'],
       'status' => $this->status,
       'weight' => $this->weight,
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php
index 5b231a9..ee4ba2b 100644
--- a/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/FilterInterface.php
@@ -7,6 +7,9 @@
 
 namespace Drupal\filter\Plugin;
 
+use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+
 /**
  * Defines the interface for text processing filter plugins.
  *
@@ -74,26 +77,7 @@
  *
  * @see \Drupal\filter\Plugin\Filter\FilterBase
  */
-interface FilterInterface {
-
-  /**
-   * Sets the configuration for this filter plugin instance.
-   *
-   * @param array $configuration
-   *   An associative array containing:
-   *   - status: A Boolean indicating whether the plugin is enabled.
-   *   - weight: The weight of the filter compared to others.
-   *   - settings: An associative array containing configured settings for this
-   *     filter implementation.
-   */
-  public function setPluginConfiguration(array $configuration);
-
-  /**
-   * Exports the complete configuration of this filter plugin instance.
-   *
-   * @return array
-   */
-  public function export();
+interface FilterInterface extends ConfigurablePluginInterface, PluginInspectionInterface {
 
   /**
    * Returns the processing type of this filter plugin.
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php
index b644b10..cd5a762 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterUnitTest.php
@@ -8,9 +8,7 @@
 namespace Drupal\filter\Tests;
 
 use Drupal\simpletest\DrupalUnitTestBase;
-use stdClass;
 use Drupal\filter\FilterBag;
-use Drupal\filter\Plugin\Filter\FilterCaption;
 
 /**
  * Unit tests for core filters.
@@ -24,6 +22,11 @@ class FilterUnitTest extends DrupalUnitTestBase {
    */
   public static $modules = array('filter');
 
+  /**
+   * @var \Drupal\filter\Plugin\FilterInterface[]
+   */
+  protected $filters;
+
   public static function getInfo() {
     return array(
       'name' => 'Filter module filters',
@@ -238,7 +241,7 @@ function testLineBreakFilter() {
   function testHtmlFilter() {
     // Get FilterHtml object.
     $filter = $this->filters['filter_html'];
-    $filter->setPluginConfiguration(array(
+    $filter->setConfiguration(array(
       'settings' => array(
         'allowed_html' => '<a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>',
         'filter_html_help' => 1,
@@ -285,7 +288,7 @@ function testHtmlFilter() {
   function testNoFollowFilter() {
     // Get FilterHtml object.
     $filter = $this->filters['filter_html'];
-    $filter->setPluginConfiguration(array(
+    $filter->setConfiguration(array(
       'settings' => array(
         'allowed_html' => '<a>',
         'filter_html_help' => 1,
@@ -337,7 +340,7 @@ function testHtmlEscapeFilter() {
   function testUrlFilter() {
     // Get FilterUrl object.
     $filter = $this->filters['filter_url'];
-    $filter->setPluginConfiguration(array(
+    $filter->setConfiguration(array(
       'settings' => array(
         'filter_url_length' => 496,
       )
@@ -629,7 +632,7 @@ function testUrlFilter() {
     $this->assertFilteredString($filter, $tests);
 
     // URL trimming.
-    $filter->setPluginConfiguration(array(
+    $filter->setConfiguration(array(
       'settings' => array(
         'filter_url_length' => 20,
       )
@@ -711,7 +714,7 @@ function assertFilteredString($filter, $tests) {
   function testUrlFilterContent() {
     // Get FilterUrl object.
     $filter = $this->filters['filter_url'];
-    $filter->setPluginConfiguration(array(
+    $filter->setConfiguration(array(
       'settings' => array(
         'filter_url_length' => 496,
       )
diff --git a/core/modules/filter/tests/filter_test/config/filter.format.filter_test.yml b/core/modules/filter/tests/filter_test/config/filter.format.filter_test.yml
index e5ebf83..ff0b160 100644
--- a/core/modules/filter/tests/filter_test/config/filter.format.filter_test.yml
+++ b/core/modules/filter/tests/filter_test/config/filter.format.filter_test.yml
@@ -9,16 +9,19 @@ status: '1'
 langcode: en
 filters:
   filter_html_escape:
+    plugin: filter_html_escape
     module: filter
     status: '1'
     weight: '-10'
     settings: {  }
   filter_autop:
+    plugin: filter_autop
     module: filter
     status: '1'
     weight: '0'
     settings: {  }
   filter_url:
+    plugin: filter_url
     module: filter
     status: '1'
     weight: '0'
diff --git a/core/modules/image/lib/Drupal/image/ImageEffectBag.php b/core/modules/image/lib/Drupal/image/ImageEffectBag.php
index 0bdee3b..b892675 100644
--- a/core/modules/image/lib/Drupal/image/ImageEffectBag.php
+++ b/core/modules/image/lib/Drupal/image/ImageEffectBag.php
@@ -7,73 +7,19 @@
 
 namespace Drupal\image;
 
-use Drupal\Component\Plugin\PluginBag;
-use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Component\Utility\MapArray;
 use Drupal\Component\Uuid\Uuid;
+use Drupal\Component\Plugin\DefaultPluginBag;
 
 /**
  * A collection of image effects.
  */
-class ImageEffectBag extends PluginBag {
-
-  /**
-   * The manager used to instantiate the plugins.
-   *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
-   */
-  protected $manager;
-
-  /**
-   * The initial configuration for each image effect in the bag.
-   *
-   * @var array
-   */
-  protected $configurations = array();
-
-  /**
-   * Constructs a new ImageEffectBag.
-   *
-   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
-   *   The manager to be used for instantiating plugins.
-   * @param array $configurations
-   *   (optional) An associative array containing the initial configuration for
-   *   each tour in the bag, keyed by plugin instance ID.
-   */
-  public function __construct(PluginManagerInterface $manager, array $configurations = array()) {
-    $this->manager = $manager;
-    $this->configurations = $configurations;
-
-    if (!empty($configurations)) {
-      $this->instanceIDs = MapArray::copyValuesToKeys(array_keys($configurations));
-    }
-  }
+class ImageEffectBag extends DefaultPluginBag {
 
   /**
    * {@inheritdoc}
    */
-  protected function initializePlugin($instance_id) {
-    if (!isset($this->pluginInstances[$instance_id])) {
-      $configuration = $this->configurations[$instance_id] + array('data' => array());
-      $this->pluginInstances[$instance_id] = $this->manager->createInstance($configuration['id'], $configuration);
-    }
-  }
-
-  /**
-   * Returns the current configuration of all image effects in this bag.
-   *
-   * @return array
-   *   An associative array keyed by image effect UUID, whose values are image
-   *   effect configurations.
-   */
-  public function export() {
-    $instances = array();
-    $this->rewind();
-    foreach ($this as $instance_id => $instance) {
-      $instances[$instance_id] = $instance->export();
-    }
-    return $instances;
-  }
+  protected $pluginKey = 'id';
 
   /**
    * Removes an instance ID.
@@ -96,24 +42,22 @@ public function removeInstanceID($instance_id) {
    *   The image effect configuration to set.
    *
    * @return string
+   *   The image effect UUID.
    */
-  public function setConfig(array $configuration) {
+  public function updateConfiguration(array $configuration) {
     // Derive the instance ID from the configuration.
     if (empty($configuration['uuid'])) {
       $uuid_generator = new Uuid();
       $configuration['uuid'] = $uuid_generator->generate();
     }
     $instance_id = $configuration['uuid'];
-    $this->configurations[$instance_id] = $configuration;
-    $this->get($instance_id)->setPluginConfiguration($configuration);
+    $this->setConfiguration($instance_id, $configuration);
     $this->addInstanceID($instance_id);
     return $instance_id;
   }
 
   /**
-   * Sorts all image effect instances in this bag.
-   *
-   * @return self
+   * {@inheritdoc}
    */
   public function sort() {
     uasort($this->configurations, 'drupal_sort_weight');
diff --git a/core/modules/image/lib/Drupal/image/ImageEffectBase.php b/core/modules/image/lib/Drupal/image/ImageEffectBase.php
index a4ddeb5..2babe0d 100644
--- a/core/modules/image/lib/Drupal/image/ImageEffectBase.php
+++ b/core/modules/image/lib/Drupal/image/ImageEffectBase.php
@@ -34,7 +34,7 @@
   public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
-    $this->setPluginConfiguration($configuration);
+    $this->setConfiguration($configuration);
   }
 
   /**
@@ -85,7 +85,7 @@ public function getWeight() {
   /**
    * {@inheritdoc}
    */
-  public function export() {
+  public function getConfiguration() {
     return array(
       'uuid' => $this->getUuid(),
       'id' => $this->getPluginId(),
@@ -97,7 +97,7 @@ public function export() {
   /**
    * {@inheritdoc}
    */
-  public function setPluginConfiguration(array $configuration) {
+  public function setConfiguration(array $configuration) {
     $configuration += array(
       'data' => array(),
       'uuid' => '',
diff --git a/core/modules/image/lib/Drupal/image/ImageEffectInterface.php b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php
index 05d5efd..19575e9 100644
--- a/core/modules/image/lib/Drupal/image/ImageEffectInterface.php
+++ b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php
@@ -8,11 +8,12 @@
 namespace Drupal\image;
 
 use Drupal\Component\Plugin\PluginInspectionInterface;
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
 
 /**
  * Defines the interface for image effects.
  */
-interface ImageEffectInterface extends PluginInspectionInterface {
+interface ImageEffectInterface extends PluginInspectionInterface, ConfigurablePluginInterface {
 
   /**
    * Applies an image effect to the image object.
@@ -77,26 +78,4 @@ public function getWeight();
    */
   public function setWeight($weight);
 
-  /**
-   * Exports the complete configuration of this image effect instance.
-   *
-   * @return array
-   */
-  public function export();
-
-  /**
-   * Sets the configuration for this image effect.
-   *
-   * @param array $configuration
-   *   An associative array containing:
-   *   - uuid: (optional) The image effect ID.
-   *   - weight: (optional) The weight of the image effect.
-   *   - data: (optional) An array of configuration specific to this image
-   *     effect type.
-   *
-   * @return self
-   *   This image effect.
-   */
-  public function setPluginConfiguration(array $configuration);
-
 }
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
index 4683ff6..73976f9 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
@@ -356,7 +356,7 @@ public function getEffects() {
    * {@inheritdoc}
    */
   public function saveImageEffect(array $configuration) {
-    $effect_id = $this->getEffects()->setConfig($configuration);
+    $effect_id = $this->getEffects()->updateConfiguration($configuration);
     $this->save();
     return $effect_id;
   }
@@ -366,7 +366,7 @@ public function saveImageEffect(array $configuration) {
    */
   public function getExportProperties() {
     $properties = parent::getExportProperties();
-    $properties['effects'] = $this->getEffects()->sort()->export();
+    $properties['effects'] = $this->getEffects()->sort()->getConfiguration();
     return $properties;
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php b/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php
index 76bc6d6..59255e2 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php
@@ -79,7 +79,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $description = t('The username of the user to which you would like to assign ownership.');
     $count = $this->connection->query("SELECT COUNT(*) FROM {users}")->fetchField();
     $owner_name = '';
@@ -119,7 +119,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function validate(array &$form, array &$form_state) {
+  public function validateConfigurationForm(array &$form, array &$form_state) {
     $exists = (bool) $this->connection->queryRange('SELECT 1 FROM {users} WHERE name = :name', 0, 1, array(':name' => $form_state['values']['owner_name']))->fetchField();
     if (!$exists) {
       form_set_error('owner_name', t('Enter a valid username.'));
@@ -129,7 +129,7 @@ public function validate(array &$form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['owner_uid'] = $this->connection->query('SELECT uid from {users} WHERE name = :name', array(':name' => $form_state['values']['owner_name']))->fetchField();
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Action/UnpublishByKeywordNode.php b/core/modules/node/lib/Drupal/node/Plugin/Action/UnpublishByKeywordNode.php
index 2d0f4ed..2ad65f8 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/Action/UnpublishByKeywordNode.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/Action/UnpublishByKeywordNode.php
@@ -48,7 +48,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $form['keywords'] = array(
       '#title' => t('Keywords'),
       '#type' => 'textarea',
@@ -61,7 +61,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['keywords'] = drupal_explode_tags($form_state['values']['keywords']);
   }
 
diff --git a/core/modules/php/config/filter.format.php_code.yml b/core/modules/php/config/filter.format.php_code.yml
index eb8b7a2..289ab21 100644
--- a/core/modules/php/config/filter.format.php_code.yml
+++ b/core/modules/php/config/filter.format.php_code.yml
@@ -5,6 +5,7 @@ weight: '11'
 cache: '0'
 filters:
   php_code:
+    id: php_code
     module: php
     status: '1'
     weight: '0'
diff --git a/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Action.php b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Action.php
index fe8f537..07591aa 100644
--- a/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Action.php
+++ b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Action.php
@@ -13,7 +13,7 @@
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\system\ActionConfigEntityInterface;
 use Drupal\Core\Action\ActionBag;
-use Drupal\Core\Action\ConfigurableActionInterface;
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
 
 /**
  * Defines the configured action entity.
@@ -127,7 +127,7 @@ public function execute(array $entities) {
    * {@inheritdoc}
    */
   public function isConfigurable() {
-    return $this->getPlugin() instanceof ConfigurableActionInterface;
+    return $this->getPlugin() instanceof ConfigurablePluginInterface;
   }
 
   /**
@@ -184,7 +184,7 @@ public function getExportProperties() {
   public function preSave(EntityStorageControllerInterface $storage_controller) {
     $plugin = $this->getPlugin();
     // If this plugin has any configuration, ensure that it is set.
-    if ($plugin instanceof ConfigurableActionInterface) {
+    if ($plugin instanceof ConfigurablePluginInterface) {
       $this->set('configuration', $plugin->getConfiguration());
     }
   }
diff --git a/core/modules/tour/lib/Drupal/tour/TipsBag.php b/core/modules/tour/lib/Drupal/tour/TipsBag.php
index 52ef292..275d152 100644
--- a/core/modules/tour/lib/Drupal/tour/TipsBag.php
+++ b/core/modules/tour/lib/Drupal/tour/TipsBag.php
@@ -7,75 +7,11 @@
 
 namespace Drupal\tour;
 
-use Drupal\Component\Plugin\PluginBag;
-use Drupal\Component\Plugin\PluginManagerInterface;
-use Drupal\Component\Plugin\Exception\PluginException;
-use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Plugin\DefaultPluginBag;
 
 /**
  * A collection of tips.
  */
-class TipsBag extends PluginBag {
-
-  /**
-   * The initial configuration for each tip in the bag.
-   *
-   * @var array
-   *   An associative array containing the initial configuration for each tip
-   *   in the bag, keyed by plugin instance ID.
-   */
-  protected $configurations = array();
-
-  /**
-   * The manager used to instantiate the plugins.
-   *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
-   */
-  protected $manager;
-
-  /**
-   * Constructs a TipsBag object.
-   *
-   * @param \Drupal\Component\Plugin\PluginManagerInterface $manager
-   *   The manager to be used for instantiating plugins.
-   * @param array $configurations
-   *   (optional) An associative array containing the initial configuration for
-   *   each tour in the bag, keyed by plugin instance ID.
-   */
-  public function __construct(PluginManagerInterface $manager, array $configurations = array()) {
-    $this->manager = $manager;
-    $this->configurations = $configurations;
-
-    if (!empty($configurations)) {
-      $this->instanceIDs = array_combine(array_keys($configurations), array_keys($configurations));
-    }
-  }
-
-  /**
-   * Overrides \Drupal\Component\Plugin\PluginBag::initializePlugin().
-   */
-  protected function initializePlugin($instance_id) {
-    // If the tip was initialized before, just return.
-    if (isset($this->pluginInstances[$instance_id])) {
-      return;
-    }
-
-    $type = $this->configurations[$instance_id]['plugin'];
-    $definition = $this->manager->getDefinition($type);
-
-    if (isset($definition)) {
-      $this->addInstanceID($instance_id);
-      $configuration = $definition;
-
-      // Merge the actual configuration into the default configuration.
-      if (isset($this->configurations[$instance_id])) {
-        $configuration = NestedArray::mergeDeep($configuration, $this->configurations[$instance_id]);
-      }
-      $this->pluginInstances[$instance_id] = $this->manager->createInstance($type, $configuration);
-    }
-    else {
-      throw new PluginException(format_string("Unknown tip plugin ID '@tip'.", array('@tip' => $instance_id)));
-    }
-  }
+class TipsBag extends DefaultPluginBag {
 
 }
diff --git a/core/modules/user/lib/Drupal/user/Plugin/Action/ChangeUserRoleBase.php b/core/modules/user/lib/Drupal/user/Plugin/Action/ChangeUserRoleBase.php
index 9dfb056..079f066 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/Action/ChangeUserRoleBase.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/Action/ChangeUserRoleBase.php
@@ -26,7 +26,7 @@ protected function getDefaultConfiguration() {
   /**
    * {@inheritdoc}
    */
-  public function form(array $form, array &$form_state) {
+  public function buildConfigurationForm(array $form, array &$form_state) {
     $roles = user_role_names(TRUE);
     unset($roles[DRUPAL_AUTHENTICATED_RID]);
     $form['rid'] = array(
@@ -42,7 +42,7 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function submit(array &$form, array &$form_state) {
+  public function submitConfigurationForm(array &$form, array &$form_state) {
     $this->configuration['rid'] = $form_state['values']['rid'];
   }
 
diff --git a/core/modules/views/lib/Drupal/views/DisplayBag.php b/core/modules/views/lib/Drupal/views/DisplayBag.php
index 9e76113..167212e 100644
--- a/core/modules/views/lib/Drupal/views/DisplayBag.php
+++ b/core/modules/views/lib/Drupal/views/DisplayBag.php
@@ -8,14 +8,13 @@
 namespace Drupal\views;
 
 use Drupal\Component\Plugin\Exception\PluginException;
-use Drupal\Component\Plugin\PluginBag;
 use Drupal\Component\Plugin\PluginManagerInterface;
-use Drupal\Component\Utility\MapArray;
+use Drupal\Component\Plugin\DefaultPluginBag;
 
 /**
  * A class which wraps the displays of a view so you can lazy-initialize them.
  */
-class DisplayBag extends PluginBag {
+class DisplayBag extends DefaultPluginBag {
 
   /**
    * Stores a reference to the view which has this displays attached.
@@ -25,11 +24,9 @@ class DisplayBag extends PluginBag {
   protected $view;
 
   /**
-   * The manager used to instantiate the plugins.
-   *
-   * @var \Drupal\Component\Plugin\PluginManagerInterface
+   * {@inheritdoc}
    */
-  protected $manager;
+  protected $pluginKey = 'display_plugin';
 
   /**
    * Constructs a DisplayBag object.
@@ -40,14 +37,10 @@ class DisplayBag extends PluginBag {
    *   The manager to be used for instantiating plugins.
    */
   public function __construct(ViewExecutable $view, PluginManagerInterface $manager) {
-    $this->view = $view;
-    $this->manager = $manager;
+    parent::__construct($manager, $view->storage->get('display'));
 
+    $this->view = $view;
     $this->initializePlugin('default');
-
-    // Store all display IDs to access them easy and fast.
-    $display = $this->view->storage->get('display');
-    $this->instanceIDs = MapArray::copyValuesToKeys(array_keys($display));
   }
 
   /**
@@ -69,7 +62,7 @@ public function clear() {
   }
 
   /**
-   * Overrides \Drupal\Component\Plugin\PluginBag::initializePlugin().
+   * {@inheritdoc}
    */
   protected function initializePlugin($display_id) {
     // If the display was initialized before, just return.
@@ -81,7 +74,8 @@ protected function initializePlugin($display_id) {
     $display = &$this->view->storage->getDisplay($display_id);
 
     try {
-      $this->pluginInstances[$display_id] = $this->manager->createInstance($display['display_plugin']);
+      $this->configurations[$display_id] = $display;
+      parent::initializePlugin($display_id);
     }
     // Catch any plugin exceptions that are thrown. So we can fail nicely if a
     // display plugin isn't found.
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php
index 4e6d775..9df4a18 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Block/ViewsBlock.php
@@ -96,8 +96,8 @@ public function access() {
   /**
    * Overrides \Drupal\block\BlockBase::form().
    */
-  public function form($form, &$form_state) {
-    $form = parent::form($form, $form_state);
+  public function buildConfigurationForm(array $form, array &$form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
 
     // Set the default label to '' so the views internal title is used.
     $form['label']['#default_value'] = '';
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
index f374907..322c7e9 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
@@ -99,6 +99,21 @@
    */
   protected $usesAreas = TRUE;
 
+  /**
+   * Constructs a new DisplayPluginBase object.
+   *
+   * Because DisplayPluginBase::initDisplay() takes the display configuration by
+   * reference and handles it differently than usual plugin configuration, pass
+   * an empty array of configuration to the parent. This prevents our
+   * configuration from being duplicated.
+   *
+   * @todo Replace DisplayPluginBase::$display with
+   *   DisplayPluginBase::$configuration to standardize with other plugins.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    parent::__construct(array(), $plugin_id, $plugin_definition);
+  }
+
   public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
     $this->setOptionDefaults($this->options, $this->defineOptions());
     $this->view = $view;
diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
index 9dd1295..2bd806e 100644
--- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
+++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewListControllerTest.php
@@ -89,12 +89,27 @@ public function testBuildRowEntityList() {
       array(array(), 'default', $display_manager->getDefinition('embed'))
     );
 
+    $values = array();
+    $values['status'] = FALSE;
+    $values['display']['default']['id'] = 'default';
+    $values['display']['default']['display_title'] = 'Display';
+    $values['display']['default']['display_plugin'] = 'default';
+
+    $values['display']['page_1']['id'] = 'page_1';
+    $values['display']['page_1']['display_title'] = 'Page 1';
+    $values['display']['page_1']['display_plugin'] = 'page';
+    $values['display']['page_1']['display_options']['path'] = 'test_page';
+
+    $values['display']['embed']['id'] = 'embed';
+    $values['display']['embed']['display_title'] = 'Embedded';
+    $values['display']['embed']['display_plugin'] = 'embed';
+
     $display_manager->expects($this->any())
       ->method('createInstance')
       ->will($this->returnValueMap(array(
-        array('default', array(), $default_display),
-        array('page', array(), $page_display),
-        array('embed', array(), $embed_display),
+        array('default', $values['display']['default'], $default_display),
+        array('page', $values['display']['page_1'], $page_display),
+        array('embed', $values['display']['embed'], $embed_display),
       )));
 
     $container = new ContainerBuilder();
@@ -114,21 +129,6 @@ public function testBuildRowEntityList() {
       ->method('buildOperations')
       ->will($this->returnValue(array()));
 
-    $values = array();
-    $values['status'] = FALSE;
-    $values['display']['default']['id'] = 'default';
-    $values['display']['default']['display_title'] = 'Display';
-    $values['display']['default']['display_plugin'] = 'default';
-
-    $values['display']['page_1']['id'] = 'page_1';
-    $values['display']['page_1']['display_title'] = 'Page 1';
-    $values['display']['page_1']['display_plugin'] = 'page';
-    $values['display']['page_1']['display_options']['path'] = 'test_page';
-
-    $values['display']['embed']['id'] = 'embed';
-    $values['display']['embed']['display_title'] = 'Embedded';
-    $values['display']['embed']['display_plugin'] = 'embed';
-
     $view = new View($values, 'view');
 
     $row = $view_list_controller->buildRow($view);
diff --git a/core/profiles/standard/config/filter.format.basic_html.yml b/core/profiles/standard/config/filter.format.basic_html.yml
index 69fc520..3545900 100644
--- a/core/profiles/standard/config/filter.format.basic_html.yml
+++ b/core/profiles/standard/config/filter.format.basic_html.yml
@@ -7,6 +7,7 @@ roles:
 cache: '1'
 filters:
   filter_html:
+    id: filter_html
     module: filter
     status: '1'
     weight: '-10'
@@ -15,16 +16,19 @@ filters:
       filter_html_help: '0'
       filter_html_nofollow: '0'
   filter_caption:
+    id: filter_caption
     module: filter
     status: '1'
     weight: '8'
     settings: {  }
   filter_html_image_secure:
+    id: filter_html_image_secure
     module: filter
     status: '1'
     weight: '9'
     settings: {  }
   filter_htmlcorrector:
+    id: filter_htmlcorrector
     module: filter
     status: '1'
     weight: '10'
diff --git a/core/profiles/standard/config/filter.format.full_html.yml b/core/profiles/standard/config/filter.format.full_html.yml
index 0265845..be674aa 100644
--- a/core/profiles/standard/config/filter.format.full_html.yml
+++ b/core/profiles/standard/config/filter.format.full_html.yml
@@ -7,11 +7,13 @@ roles:
 cache: '1'
 filters:
   filter_caption:
+    id: filter_caption
     module: filter
     status: '1'
     weight: '9'
     settings: {  }
   filter_htmlcorrector:
+    id: filter_htmlcorrector
     module: filter
     status: '1'
     weight: '10'
diff --git a/core/profiles/standard/config/filter.format.restricted_html.yml b/core/profiles/standard/config/filter.format.restricted_html.yml
index 40203fe..8ed981e 100644
--- a/core/profiles/standard/config/filter.format.restricted_html.yml
+++ b/core/profiles/standard/config/filter.format.restricted_html.yml
@@ -7,6 +7,7 @@ roles:
 cache: '1'
 filters:
   filter_html:
+    id: filter_html
     module: filter
     status: '1'
     weight: '-10'
@@ -15,17 +16,20 @@ filters:
       filter_html_help: '1'
       filter_html_nofollow: '0'
   filter_autop:
+    id: filter_autop
     module: filter
     status: '1'
     weight: '0'
     settings: {  }
   filter_url:
+    id: filter_url
     module: filter
     status: '1'
     weight: '0'
     settings:
       filter_url_length: '72'
   filter_htmlcorrector:
+    id: filter_htmlcorrector
     module: filter
     status: '1'
     weight: '10'
