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..3a1904c
--- /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 $plugin_id => $definition) {
+      $definitions[$plugin_id] = 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 73f1b55..ee6e72c 100644
--- a/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
+++ b/core/lib/Drupal/Component/Plugin/PluginManagerBase.php
@@ -34,15 +34,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) {
@@ -87,6 +78,6 @@ public function getInstance(array $options) {
    * method.
    */
   protected function processDefinition(&$definition, $plugin_id) {
-    $definition += $this->defaults;
   }
+
 }
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/lib/Drupal/system/Tests/Plugin/InspectionTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/InspectionTest.php
index dcdaa34..5daf1e9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/InspectionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/InspectionTest.php
@@ -27,14 +27,20 @@ function testInspection() {
     foreach (array('user_login') as $id) {
       $plugin = $this->testPluginManager->createInstance($id);
       $this->assertIdentical($plugin->getPluginId(), $id);
-      $this->assertIdentical($plugin->getDefinition(), $this->testPluginExpectedDefinitions[$id]);
+      $this->assertIdentical($this->testPluginManager->getDefinition($id), $this->testPluginExpectedDefinitions[$id]);
     }
     // Skip the 'menu' derived blocks, because MockMenuBlock does not implement
     // PluginInspectionInterface. The others do by extending PluginBase.
     foreach (array('user_login', 'layout') as $id) {
       $plugin = $this->mockBlockManager->createInstance($id);
       $this->assertIdentical($plugin->getPluginId(), $id);
-      $this->assertIdentical($plugin->getDefinition(), $this->mockBlockExpectedDefinitions[$id]);
+      $this->assertIdentical($this->mockBlockManager->getDefinition($id), $this->mockBlockExpectedDefinitions[$id]);
+    }
+    // Test a plugin manager that provides defaults.
+    foreach (array('test_block1', 'test_block2') as $id) {
+      $plugin = $this->defaultsTestPluginManager->createInstance($id);
+      $this->assertIdentical($plugin->getPluginId(), $id);
+      $this->assertIdentical($this->defaultsTestPluginManager->getDefinition($id), $this->defaultsTestPluginExpectedDefinitions[$id]);
     }
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php
index 5595e28..5db9322 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php
@@ -10,6 +10,7 @@
 use Drupal\simpletest\UnitTestBase;
 use Drupal\plugin_test\Plugin\TestPluginManager;
 use Drupal\plugin_test\Plugin\MockBlockManager;
+use Drupal\plugin_test\Plugin\DefaultsTestPluginManager;
 
 /**
  * Base class for Plugin API unit tests.
@@ -19,6 +20,8 @@
   protected $testPluginExpectedDefinitions;
   protected $mockBlockManager;
   protected $mockBlockExpectedDefinitions;
+  protected $defaultsTestPluginManager;
+  protected $defaultsTestPluginExpectedDefinitions;
 
   public function setUp() {
     parent::setUp();
@@ -33,6 +36,7 @@ public function setUp() {
     //   as derivatives and ReflectionFactory.
     $this->testPluginManager = new TestPluginManager();
     $this->mockBlockManager = new MockBlockManager();
+    $this->defaultsTestPluginManager = new DefaultsTestPluginManager();
 
     // The expected plugin definitions within each manager. Several tests assert
     // that these plugins and their definitions are found and returned by the
@@ -67,5 +71,22 @@ public function setUp() {
         'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock',
       ),
     );
+    $this->defaultsTestPluginExpectedDefinitions = array(
+      'test_block1' => array(
+        'metadata' => array(
+          'default' => TRUE,
+          'custom' => TRUE,
+        ),
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockTestBlock',
+      ),
+      'test_block2' => array(
+        'metadata' => array(
+          'default' => FALSE,
+          'custom' => TRUE,
+        ),
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockTestBlock',
+      ),
+    );
   }
+
 }
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
new file mode 100644
index 0000000..607b100
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/DefaultsTestPluginManager.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\plugin_test\Plugin\DefaultsTestPluginManager.
+ */
+
+namespace Drupal\plugin_test\Plugin;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Component\Plugin\Discovery\StaticDiscovery;
+use Drupal\Component\Plugin\Factory\DefaultFactory;
+
+/**
+ * Defines a plugin manager used by Plugin API unit tests.
+ */
+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(
+      'metadata' => array(
+        'default' => TRUE,
+      ),
+    );
+
+    // Add a plugin with a custom value.
+    $this->discovery->setDefinition('test_block1', array(
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockTestBlock',
+      'metadata' => array(
+        'custom' => TRUE,
+      ),
+    ));
+    // Add a plugin that overrides the default value.
+    $this->discovery->setDefinition('test_block2', array(
+      'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockTestBlock',
+      'metadata' => array(
+        'custom' => TRUE,
+        'default' => FALSE,
+      ),
+    ));
+  }
+
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockTestBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockTestBlock.php
new file mode 100644
index 0000000..63ea928
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockTestBlock.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\plugin_test\Plugin\plugin_test\mock_block\MockTestBlock.
+ */
+
+namespace Drupal\plugin_test\Plugin\plugin_test\mock_block;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+
+/**
+ * Mock implementation of a test block plugin used by Plugin API unit tests.
+ *
+ * @see Drupal\plugin_test\Plugin\DefaultsTestPluginManager
+ */
+class MockTestBlock extends PluginBase {
+
+}
