diff --git a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php b/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
index 281a4ca..ad2e04b 100644
--- a/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
+++ b/core/lib/Drupal/Component/Plugin/Derivative/DerivativeInterface.php
@@ -11,9 +11,6 @@ namespace Drupal\Component\Plugin\Derivative;
  */
 interface DerivativeInterface {
 
-
-  public function __construct($scope, $type, $plugin, array $config);
-
   /**
    * Set a specific derivative for the instance to return.
    *
@@ -31,6 +28,6 @@ interface DerivativeInterface {
    *   An array of Configuration objects for all potential derivatives of this
    *   plugin implementation.
    */
-  public function getDerivatives();
+  public static function getDerivatives();
 
 }
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryAbstract.php b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryAbstract.php
new file mode 100644
index 0000000..057756c
--- /dev/null
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryAbstract.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * ...
+ */
+
+namespace Drupal\Component\Plugin\Discovery;
+
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+
+abstract class DiscoveryAbstract implements DiscoveryInterface {
+
+  public function getPluginDefinition($plugin_id) {}
+
+  public function getPluginDefinitions() {}
+
+  public function derivePluginId($plugin) {
+    @list($plugin_id, $derivative) = explode(':', $plugin, 2);
+    return array($plugin_id, $derivative);
+  }
+
+  public function getDerivative(array $definition, $derivative) {
+    if (isset($definition['derivative'])) {
+      $derviative_mapper = new $definition['derivative']();
+      $config = $derviative_mapper->getDerivative($derivative);
+      foreach ($definition as $element => $value) {
+        if (!isset($config[$element])) {
+          $config[$element] = $value;
+        }
+      }
+      return $config;
+    }
+    return array();
+  }
+
+  /**
+   * Implements DiscoveryInterface::getPluginDefinitions().
+   */
+  public function getDerivatives() {
+    $definitions = array();
+    if (isset($this->plugin_definitions)) {
+      foreach ($this->plugin_definitions as $id => $definition) {
+        if (isset($definition['derivative'])) {
+          $definitions += $definition['derivative']::getDerivatives();
+        }
+        else {
+          $definitions[$id] = $definition;
+        }
+      }
+    }
+    return $definitions;
+  }
+
+}
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php
index 1d787c3..72f4e69 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscovery.php
@@ -9,7 +9,7 @@ namespace Drupal\Component\Plugin\Discovery;
 /**
  *
  */
-class StaticDiscovery implements DiscoveryInterface {
+class StaticDiscovery extends DiscoveryAbstract {
 
   protected $plugin_definitions = array();
 
@@ -17,14 +17,35 @@ class StaticDiscovery implements DiscoveryInterface {
    * Implements DiscoveryInterface::getPluginDefinition().
    */
   public function getPluginDefinition($plugin) {
-    return isset($this->plugin_definitions[$plugin]) ? $this->plugin_definitions[$plugin] : array();
+    list($plugin_id, $derivative) = $this->derivePluginId($plugin);
+    if (isset($this->plugin_definitions[$plugin_id])) {
+      if ($derivative && !empty($this->plugin_definitions[$plugin_id]['derivative'])) {
+        return $this->getDerivative($this->plugin_definitions[$plugin_id], $derivative);
+      }
+      elseif (!empty($this->plugin_definitions[$plugin_id]['derivative'])) {
+        return array();
+      }
+      return $this->plugin_definitions[$plugin_id];
+    }
+    return array();
   }
 
   /**
    * Implements DiscoveryInterface::getPluginDefinitions().
    */
   public function getPluginDefinitions() {
-    return isset($this->plugin_definitions) ? $this->plugin_definitions : array();
+    $definitions = array();
+    if (isset($this->plugin_definitions)) {
+      foreach ($this->plugin_definitions as $id => $definition) {
+        if (isset($definition['derivative'])) {
+          $definitions += $definition['derivative']::getDerivatives();
+        }
+        else {
+          $definitions[$id] = $definition;
+        }
+      }
+    }
+    return $definitions;
   }
 
   /**
diff --git a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
index 2d81ed9..a6f37b0 100644
--- a/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
+++ b/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php
@@ -19,6 +19,7 @@ class DefaultFactory implements FactoryInterface {
 
   protected $discovery;
   protected $class_key;
+  protected $plugin_definition;
 
   public function __construct(DiscoveryInterface $discovery, $class_key) {
     $this->discovery = $discovery;
@@ -45,7 +46,9 @@ class DefaultFactory implements FactoryInterface {
     else {
       $instance = new $plugin_class();
     }
-    $instance->setConfig($configuration);
+    if (!empty($configuration['config'])) {
+      $instance->setConfig($configuration['config']);
+    }
 
     return $instance;
   }
@@ -64,12 +67,12 @@ class DefaultFactory implements FactoryInterface {
       throw new PluginException("The plugin type did not specify a valid key for determining the plugin instance class.");
     }
 
-    $plugin_definition = $this->discovery->getPluginDefinition($plugin_id);
-    if (empty($plugin_definition[$this->class_key])) {
+    $this->plugin_definition = $this->discovery->getPluginDefinition($plugin_id);
+    if (empty($this->plugin_definition[$this->class_key])) {
       throw new PluginException("The plugin did not specify an instance class.");
     }
 
-    $class = $plugin_definition[$this->class_key];
+    $class = $this->plugin_definition[$this->class_key];
 
     if (!class_exists($class)) {
       throw new PluginException(t("Plugin instance class @class does not exist.", array('@class' => $class)));
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/ConfigDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/ConfigDiscovery.php
index c160b1a..70a7b03 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/ConfigDiscovery.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/ConfigDiscovery.php
@@ -22,7 +22,7 @@ class ConfigDiscovery implements DiscoveryInterface {
   public function getPluginDefinition($plugin_id) {
     $config = config("{$this->definition_root}.$plugin_id")->get();
     if ($config['derivative']) {
-      $derviative_mapper = new $config['derivative']($this->definition_root, $plugin_id, $config);
+      $derviative_mapper = new $config['derivative']();
       $config = $derviative_mapper->getDerviative($plugin_id);
     }
     return $config;
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php
new file mode 100644
index 0000000..3f8ab06
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Derivative/DerivativeTest.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Drupal\plugin_test\Plugin\Derivative;
+
+use Drupal\Component\Plugin\Derivative\DerivativeInterface;
+
+class DerivativeTest implements DerivativeInterface {
+  /**
+   * Implement DerivativeInterface::getDerivative().
+   */
+  public function getDerivative($key) {
+    $derivatives = $this->getDerivatives();
+    return isset($derivatives[$key]) ? $derivatives[$key] : FALSE;
+  }
+
+  /**
+   * Implement DerivativeInterface::getDerivatives().
+   */
+  public static function getDerivatives() {
+    return array(
+      'test1' => array(
+        'string' => 'Test String 1',
+      ),
+      'test2' => array(
+        'string' => 'Test String 2',
+      ),
+    );
+  }
+}
\ No newline at end of file
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginInstanceClass.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginInstanceClass.php
index 0febf83..c063a5a 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginInstanceClass.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/TestPluginInstanceClass.php
@@ -9,4 +9,7 @@ namespace Drupal\plugin_test\Plugin;
 use Drupal\Component\Plugin\PluginAbstract;
 
 class TestPluginInstanceClass extends PluginAbstract {
+  public function string() {
+    return $this->config['string'];
+  }
 }
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Type/TestPluginType.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Type/TestPluginType.php
index 74799db..3207434 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Type/TestPluginType.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/Type/TestPluginType.php
@@ -10,6 +10,7 @@ use Drupal\Component\Plugin\PluginType;
 use Drupal\Component\Plugin\Discovery\StaticDiscovery;
 use Drupal\Component\Plugin\Mapper\DefaultMapper;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
+use Drupal\plugin_test\Plugin\Derivative\DerivativeTest;
 
 class TestPluginType extends PluginType {
   public function __construct() {
@@ -18,6 +19,11 @@ class TestPluginType extends PluginType {
       'string' => 'oh yeah',
       'class' => 'Drupal\plugin_test\Plugin\TestPluginInstanceClass',
     ));
+    $this->discovery->setPluginDefinition('beer', array(
+      'string' => 'derivative test',
+      'class' => 'Drupal\plugin_test\Plugin\TestPluginInstanceClass',
+      'derivative' => 'Drupal\plugin_test\Plugin\Derivative\DerivativeTest',
+    ));
     $this->factory = new DefaultFactory($this->discovery, 'class');
     $this->mapper = new DefaultMapper($this->discovery, $this->factory);
   }
diff --git a/core/modules/system/tests/plugins.test b/core/modules/system/tests/plugins.test
index 0966593..a9856b7 100644
--- a/core/modules/system/tests/plugins.test
+++ b/core/modules/system/tests/plugins.test
@@ -1,49 +1,9 @@
 <?php
 
-use Symfony\Component\ClassLoader\UniversalClassLoader;
 use Drupal\plugin_test\Plugin\Type\TestPluginType;
 
-abstract class PluginUnitTestCase extends DrupalUnitTestCase {
-  protected $loader;
-
-  public function setUp() {
-    parent::setUp();
-    // We're a unit test using classes... don't let the db registry blow up.
-    spl_autoload_unregister('drupal_autoload_class');
-    spl_autoload_unregister('drupal_autoload_interface');
-
-    // At some point, we may have tests that require plugin_test.module to be
-    // enabled, but that would require a DrupalWebTestCase rather than a
-    // DrupalUnitTestCase, which incurs performance overhead. For now, the test
-    // module's only purpose is to expose some classes, so register it with the
-    // autoloader despite it not being enabled.
-
-    // Make sure the Symfony classloader file is included. This is just good
-    // measure since the Core class loader should have been called by this point.
-    drupal_classloader();
-    // Register a new class loader so we don't polute the global class loader
-    // and potencially affect other tests.
-    $this->loader = new UniversalClassLoader();
-    $this->loader->registerNamespace('Drupal\\plugin_test', dirname(__FILE__) . '/modules/plugin_test/lib');
-    $this->loader->register();
-  }
-
-  public function tearDown() {
-    // Re-register autoloaders before tearDown begins.
-    spl_autoload_register('drupal_autoload_interface');
-    spl_autoload_register('drupal_autoload_class');
-
-    // Be as reentrant as simpletest will allow. The classes loaded will still
-    // avaiable to php but hopefully we're not leaking dead autoloaders.
-    spl_autoload_unregister(array($this->loader, 'loadClass'));
-
-    // Let simpletest finish tearing down the test.
-    parent::tearDown();
-  }
-}
-
-class PluginTestCase extends PluginUnitTestCase {
-  protected $TestPluginType;
+class PluginTestCase extends DrupalUnitTestCase {
+  protected $test_plugin_type;
 
   public static function getInfo() {
     return array(
@@ -56,19 +16,62 @@ class PluginTestCase extends PluginUnitTestCase {
   public function setUp() {
     parent::setUp();
 
+    // At some point, we may have tests that require plugin_test.module to be
+    // enabled, but that would require a DrupalWebTestCase rather than a
+    // DrupalUnitTestCase, which incurs performance overhead. For now, the test
+    // module's only purpose is to expose some classes, so register it with the
+    // autoloader despite it not being enabled.
+    drupal_classloader_register('plugin_test', drupal_get_path('module', 'plugin_test'));
+
     // Real modules implementing plugin types may expose a module-specific API
     // for retrieving its plugin type objects, but for unit testing, we can get
     // the object directly.
-    $this->TestPluginType = new TestPluginType();
+    $this->test_plugin_type = new TestPluginType;
   }
 
   function testPluginDefintionFetching() {
-    $plugin_definition = $this->TestPluginType->getPluginDefinition('coolaid');
+    $plugin_definition = $this->test_plugin_type->getPluginDefinition('coolaid');
     $this->assertEqual($plugin_definition['string'], 'oh yeah', 'Plugin definition retrievable by the test plugin type.');
   }
 
   function testPluginInstanceFetching() {
-    $plugin = $this->TestPluginType->createPluginInstance('coolaid');
+    $plugin = $this->test_plugin_type->createPluginInstance('coolaid', array('config' => array('string' => 'this is a test')));
     $this->assertEqual(get_class($plugin), 'Drupal\plugin_test\Plugin\TestPluginInstanceClass', 'Correct plugin instance implementation returned by the test plugin type.');
+    $this->assertEqual($plugin->string(), 'this is a test', 'Plugin instance returns the proper string');
+  }
+
+  function testPluginDerivativeDefintionFetching() {
+    $plugin_definition = $this->test_plugin_type->getPluginDefinition('beer:test1');
+    $this->assertEqual($plugin_definition['string'], 'Test String 1', 'Plugin derivative definition retrievable by the test plugin type.');
+  }
+
+  function testPluginEmptyDerivativeDefintionFetching() {
+    $plugin_definition = $this->test_plugin_type->getPluginDefinition('beer');
+    $this->assertFalse($plugin_definition, 'Plugin derivative definition was not retrievable by the test plugin type.');
+  }
+
+  function testPluginInstanceDerivativeFetching() {
+    $plugin_definition = $this->test_plugin_type->getPluginDefinition('beer:test1');
+    $plugin = $this->test_plugin_type->createPluginInstance('beer:test1', array('config' => $plugin_definition));
+    $this->assertEqual($plugin->string(), 'Test String 1', 'Plugin derivative instance 1 returns the proper string');
+
+    $plugin_definition = $this->test_plugin_type->getPluginDefinition('beer:test2');
+    $plugin = $this->test_plugin_type->createPluginInstance('beer:test2', array('config' => $plugin_definition));
+    $this->assertEqual($plugin->string(), 'Test String 2', 'Plugin derivative instance 2 returns the proper string');
+  }
+
+  function testPluginEmptyDerivativeInstanceFetching() {
+    try {
+      $plugin = $this->test_plugin_type->createPluginInstance('beer');
+      $this->fail('Drupal\Component\Plugin\PluginException expected');
+    }
+    catch (Exception $e) {
+      if ($e instanceof Drupal\Component\Plugin\PluginException) {
+        $this->pass('Drupal\Component\Plugin\PluginException expected and caught.');
+      }
+      else {
+        $this->fail('Drupal\Component\Plugin\PluginException expected');
+      }
+    }
   }
 }
