 .../Plugin/Discovery/DefaultsDecorator.php         | 72 ++++++++++++++++++++++
 .../Drupal/Component/Plugin/PluginManagerBase.php  | 17 +----
 .../Type/Formatter/FormatterPluginManager.php      | 15 ++---
 .../Plugin/Type/Widget/WidgetPluginManager.php     | 17 +++--
 .../Drupal/layout/Plugin/Type/LayoutManager.php    | 10 +--
 .../Plugin/DefaultsTestPluginManager.php           | 16 ++---
 .../lib/Drupal/views/Plugin/Type/JoinManager.php   |  7 ++-
 .../lib/Drupal/views/Plugin/Type/PluginManager.php |  7 ++-
 .../lib/Drupal/views/Plugin/Type/WizardManager.php |  7 ++-
 9 files changed, 111 insertions(+), 57 deletions(-)

diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DefaultsDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/DefaultsDecorator.php
new file mode 100644
index 0000000..3466403
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DefaultsDecorator.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Component\Plugin\Discovery\DefaultsDecorator.
+ */
+
+namespace Drupal\Component\Plugin\Discovery;
+
+use Drupal\Component\Utility\NestedArray;
+
+/**
+ * Discovery decorator that applies defaults to each plugin definition.
+ */
+class DefaultsDecorator implements DiscoveryInterface {
+
+  /**
+   * The parent object implementing DiscoveryInterface that is being decorated.
+   *
+   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
+   */
+  protected $decorated;
+
+  /**
+   * An array of defaults that will be added to each plugin definition.
+   *
+   * @var array
+   */
+  protected $defaults;
+
+  /**
+   * Constructs a DefaultsDecorator object.
+   *
+   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
+   *   The parent object implementing DiscoveryInterface that is being
+   *   decorated.
+   * @param array $defaults
+   *   An array of defaults that will be merged onto each plugin definition
+   *   using \Drupal\Component\Utility\NestedArray::mergeDeep().
+   */
+  public function __construct(DiscoveryInterface $decorated, $defaults) {
+    $this->decorated = $decorated;
+    $this->defaults = $defaults;
+  }
+
+  /**
+   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinition().
+   */
+  public function getDefinition($plugin_id) {
+    $definitions = $this->getDefinitions();
+    return isset($definitions[$plugin_id]) ? $definitions[$plugin_id] : NULL;
+  }
+
+  /**
+   * Implements Drupal\Component\Plugin\Discovery\DiscoveryInterface::getDefinitions().
+   */
+  public function getDefinitions() {
+    $definitions = $this->decorated->getDefinitions();
+    foreach ($definitions as &$definition) {
+      $definition = NestedArray::mergeDeep($this->defaults, $definition);
+    }
+    return $definitions;
+  }
+
+  /**
+   * Passes through all unknown calls onto the decorated object.
+   */
+  public function __call($method, $args) {
+    return call_user_func_array(array($this->decorated, $method), $args);
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/PluginManagerBase.php b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
index e4131fc..5f95873 100644
--- a/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
+++ b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
@@ -36,15 +36,6 @@
   protected $mapper;
 
   /**
-   * A set of defaults to be referenced by $this->processDefinition() if
-   * additional processing of plugins is necessary or helpful for development
-   * purposes.
-   *
-   * @var array
-   */
-  protected $defaults = array();
-
-  /**
    * Implements Drupal\Component\Plugin\PluginManagerInterface::getDefinition().
    */
   public function getDefinition($plugin_id) {
@@ -83,13 +74,7 @@ public function getInstance(array $options) {
 
   /**
    * Performs extra processing on plugin definitions.
-   *
-   * By default we add defaults for the type to the definition. If a type has
-   * additional processing logic they can do that by replacing or extending the
-   * method.
    */
-  protected function processDefinition(&$definition, $plugin_id) {
-    $definition = NestedArray::mergeDeep($this->defaults, $definition);
-  }
+  protected function processDefinition(&$definition, $plugin_id) {}
 
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
index 6dc4163..c59ed6a 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
@@ -8,6 +8,7 @@
 namespace Drupal\field\Plugin\Type\Formatter;
 
 use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\field\Plugin\Type\Formatter\FormatterLegacyDiscoveryDecorator;
@@ -19,14 +20,6 @@
 class FormatterPluginManager extends PluginManagerBase {
 
   /**
-   * Overrides Drupal\Component\Plugin\PluginManagerBase:$defaults.
-   */
-  protected $defaults = array(
-    'settings' => array(),
-    'default_value' => TRUE,
-  );
-
-  /**
    * The cache bin used for plugin definitions.
    *
    * @var string
@@ -44,7 +37,11 @@ class FormatterPluginManager extends PluginManagerBase {
    * Constructs a FormatterPluginManager object.
    */
   public function __construct() {
-    $this->baseDiscovery = new AlterDecorator(new FormatterLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'formatter')), 'field_formatter_info');
+    $defaults = array(
+      'settings' => array(),
+      'default_value' => TRUE,
+    );
+    $this->baseDiscovery = new AlterDecorator(new DefaultsDecorator(new FormatterLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'formatter')), $defaults), 'field_formatter_info');
     $this->discovery = new CacheDecorator($this->baseDiscovery, $this->cache_id, $this->cache_bin);
 
     $this->factory = new FormatterFactory($this);
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
index d0410e0..88b1834 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\field\Plugin\Type\Widget;
 
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
@@ -18,15 +19,6 @@
 class WidgetPluginManager extends PluginManagerBase {
 
   /**
-   * Overrides Drupal\Component\Plugin\PluginManagerBase:$defaults.
-   */
-  protected $defaults = array(
-    'settings' => array(),
-    'multiple_values' => FALSE,
-    'default_value' => TRUE,
-  );
-
-  /**
    * The cache bin used for plugin definitions.
    *
    * @var string
@@ -44,7 +36,12 @@ class WidgetPluginManager extends PluginManagerBase {
    * Constructs a WidgetPluginManager object.
    */
   public function __construct() {
-    $this->baseDiscovery = new WidgetLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'widget'));
+    $defaults = array(
+      'settings' => array(),
+      'multiple_values' => FALSE,
+      'default_value' => TRUE,
+    );
+    $this->baseDiscovery = new DefaultsDecorator(new WidgetLegacyDiscoveryDecorator(new AnnotatedClassDiscovery('field', 'widget')), $defaults);
     $this->discovery = new CacheDecorator($this->baseDiscovery, $this->cache_id, $this->cache_bin);
 
     $this->factory = new WidgetFactory($this);
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php b/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
index e58ad4b..c0ec976 100644
--- a/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Type/LayoutManager.php
@@ -8,6 +8,7 @@
 namespace Drupal\layout\Plugin\Type;
 
 use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Component\Plugin\Factory\ReflectionFactory;
@@ -17,16 +18,15 @@
  */
 class LayoutManager extends PluginManagerBase {
 
-  protected $defaults = array(
-    'class' => 'Drupal\layout\Plugin\layout\layout\StaticLayout',
-  );
-
   /**
    * Overrides Drupal\Component\Plugin\PluginManagerBase::__construct().
    */
   public function __construct() {
+    $defaults = array(
+      'class' => 'Drupal\layout\Plugin\layout\layout\StaticLayout',
+    );
     // Create layout plugin derivatives from declaratively defined layouts.
-    $this->discovery = new DerivativeDiscoveryDecorator(new AnnotatedClassDiscovery('layout', 'layout'));
+    $this->discovery = new DefaultsDecorator(new DerivativeDiscoveryDecorator(new AnnotatedClassDiscovery('layout', 'layout')), $defaults);
     $this->factory = new ReflectionFactory($this);
   }
 }
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/DefaultsTestPluginManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/DefaultsTestPluginManager.php
index 607b100..a271dc0 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/DefaultsTestPluginManager.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/DefaultsTestPluginManager.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\Discovery\StaticDiscovery;
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 
 /**
@@ -17,20 +18,19 @@
 class DefaultsTestPluginManager extends PluginManagerBase {
 
   public function __construct() {
-    // Create the object that can be used to return definitions for all the
-    // plugins available for this type. Most real plugin managers use a richer
-    // discovery implementation, but StaticDiscovery lets us add some simple
-    // mock plugins for unit testing.
-    $this->discovery = new StaticDiscovery();
-    $this->factory = new DefaultFactory($this);
-
     // Specify default values.
-    $this->defaults = array(
+    $defaults = array(
       'metadata' => array(
         'default' => TRUE,
       ),
     );
 
+    // Create the object that can be used to return definitions for all the
+    // plugins available for this type. Use DefaultsDecorator to test that
+    // defaults are applied correctly.
+    $this->discovery = new DefaultsDecorator(new StaticDiscovery(), $defaults);
+    $this->factory = new DefaultFactory($this);
+
     // Add a plugin with a custom value.
     $this->discovery->setDefinition('test_block1', array(
       'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockTestBlock',
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php b/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php
index eac395b..3a176ad 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Type/JoinManager.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
@@ -19,11 +20,11 @@ class JoinManager extends PluginManagerBase {
    * Constructs a JoinManager object.
    */
   public function __construct() {
-    $this->discovery = new CacheDecorator(new AlterDecorator(new AnnotatedClassDiscovery('views', 'join'), 'views_plugins_join'), 'views:join', 'views_info');
-    $this->factory = new DefaultFactory($this);
-    $this->defaults = array(
+    $defaults = array(
       'module' => 'views',
     );
+    $this->discovery = new CacheDecorator(new AlterDecorator(new DefaultsDecorator(new AnnotatedClassDiscovery('views', 'join'), $defaults), 'views_plugins_join'), 'views:join', 'views_info');
+    $this->factory = new DefaultFactory($this);
   }
 
 }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php b/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php
index f5f6f6e..22f5b90 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Type/PluginManager.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
@@ -19,13 +20,13 @@ class PluginManager extends PluginManagerBase {
    * Constructs a PluginManager object.
    */
   public function __construct($type) {
-    $this->discovery = new CacheDecorator(new AlterDecorator(new AnnotatedClassDiscovery('views', $type), 'views_plugins_' . $type), 'views:' . $type, 'views_info');
-    $this->factory = new DefaultFactory($this);
-    $this->defaults += array(
+    $defaults = array(
       'parent' => 'parent',
       'plugin_type' => $type,
       'module' => 'views',
     );
+    $this->discovery = new CacheDecorator(new AlterDecorator(new DefaultsDecorator(new AnnotatedClassDiscovery('views', $type), $defaults), 'views_plugins_' . $type), 'views:' . $type, 'views_info');
+    $this->factory = new DefaultFactory($this);
   }
 
   /**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php b/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php
index 96b544f..d31e6e2 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/Type/WizardManager.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\Component\Plugin\Discovery\DefaultsDecorator;
 use Drupal\Core\Plugin\Discovery\AlterDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
@@ -19,11 +20,11 @@ class WizardManager extends PluginManagerBase {
    * Constructs a WizardManager object.
    */
   public function __construct() {
-    $this->discovery = new CacheDecorator(new AlterDecorator(new AnnotatedClassDiscovery('views', 'wizard'), 'views_plugins_wizard'), 'views:wizard', 'views_info');
-    $this->factory = new DefaultFactory($this);
-    $this->defaults = array(
+    $defaults = array(
       'module' => 'views',
     );
+    $this->discovery = new CacheDecorator(new AlterDecorator(new DefaultsDecorator(new AnnotatedClassDiscovery('views', 'wizard'), $defaults), 'views_plugins_wizard'), 'views:wizard', 'views_info');
+    $this->factory = new DefaultFactory($this);
   }
 
 }
