diff --git a/core/lib/Drupal/Core/Annotation/AnnotationInterface.php b/core/lib/Drupal/Core/Annotation/AnnotationInterface.php
new file mode 100644
index 0000000..7bf9e85
--- /dev/null
+++ b/core/lib/Drupal/Core/Annotation/AnnotationInterface.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Annotation\AnnotationInterface.
+ */
+
+namespace Drupal\Core\Annotation;
+
+interface AnnotationInterface {
+  /**
+   * Returns the value of an annotation.
+   */
+  public function get();
+}
diff --git a/core/lib/Drupal/Core/Annotation/DirectoryIterator.php b/core/lib/Drupal/Core/Annotation/DirectoryIterator.php
new file mode 100644
index 0000000..73f72ed
--- /dev/null
+++ b/core/lib/Drupal/Core/Annotation/DirectoryIterator.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Annotation\DirectoryIterator.
+ */
+
+namespace Drupal\Core\Annotation;
+
+use DirectoryIterator as PHPDirectoryIterator;
+
+/**
+ * This class exists to support pre-5.3.6 versions of php where this method
+ * does not exist. Once the requirements for core are upgraded, this class can
+ * be removed.
+ */
+class DirectoryIterator extends PHPDirectoryIterator {
+  public function getExtension() {
+    $parts = explode('.', $this->getFilename());
+    return array_pop($parts);
+  }
+}
diff --git a/core/lib/Drupal/Core/Annotation/Plugin.php b/core/lib/Drupal/Core/Annotation/Plugin.php
new file mode 100644
index 0000000..80e6135
--- /dev/null
+++ b/core/lib/Drupal/Core/Annotation/Plugin.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Annotation\Plugin.
+ */
+
+namespace Drupal\Core\Annotation;
+
+use Drupal\Core\Annotation\AnnotationInterface;
+
+/**
+ * @Annotation
+ */
+class Plugin implements AnnotationInterface {
+  protected $definition;
+
+  /**
+   * Build up the plugin definition and invoke the get() method for any classed
+   * annotations that were used.
+   */
+  public function __construct($values) {
+    foreach ($values as $key => $value) {
+      if ($value instanceof AnnotationInterface) {
+        $this->definition[$key] = $value->get();
+      }
+      else {
+        $this->definition[$key] = $value;
+      }
+    }
+  }
+
+  /**
+   * Implements AnnotationInterface::get().
+   */
+  public function get() {
+    return $this->definition;
+  }
+}
diff --git a/core/lib/Drupal/Core/Annotation/Translation.php b/core/lib/Drupal/Core/Annotation/Translation.php
new file mode 100644
index 0000000..2457b92
--- /dev/null
+++ b/core/lib/Drupal/Core/Annotation/Translation.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Annotation\Translation.
+ */
+
+namespace Drupal\Core\Annotation;
+
+use Drupal\Core\Annotation\AnnotationInterface;
+
+/**
+ * @Annotation
+ */
+class Translation implements AnnotationInterface {
+  protected $translation;
+
+  /**
+   * Parse values passed into this class through the t() function in Drupal and
+   * handle an optional context for the string.
+   */
+  public function __construct($values) {
+    $string = $values['value'];
+    $options = array();
+    if (!empty($values['context'])) {
+      $options = array(
+        'context' => $values['context'],
+      );
+    }
+    $this->translation = t($string, array(), $options);
+  }
+
+  /**
+   * Implements AnnotationInterface::get().
+   */
+  public function get() {
+    return $this->translation;
+  }
+}
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php
new file mode 100644
index 0000000..e9d7a26
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Discovery/AnnotatedClassDiscovery.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Component\Plugin\Discovery\AnnotatedClassDiscovery.
+ */
+
+namespace Drupal\Core\Plugin\Discovery;
+
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\Core\Annotation\DirectoryIterator;
+use Doctrine\Common\Annotations\AnnotationReader;
+use Doctrine\Common\Annotations\AnnotationRegistry;
+use Doctrine\Common\Reflection\StaticReflectionParser;
+use Doctrine\Common\Reflection\Psr0FindFile;
+use Drupal\Core\Annotation\Plugin;
+
+/**
+ * A discovery mechanism finds annotated plugins in PSR-0 namespaces.
+ */
+class AnnotatedClassDiscovery implements DiscoveryInterface {
+  function __construct($owner, $type) {
+    $this->owner = $owner;
+    $this->type = $type;
+  }
+
+  /**
+   * Implements DiscoveryInterface::getDefinition().
+   */
+  public function getDefinition($plugin_id) {
+    $plugins = $this->getDefinitions();
+    return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : array();
+  }
+
+  /**
+   * Implements DiscoveryInterface::getDefinitions().
+   */
+  public function getDefinitions() {
+    $definitions = array();
+    $reader = new AnnotationReader();
+    AnnotationRegistry::registerAutoloadNamespace('Drupal\Core\Annotation', array(DRUPAL_ROOT . '/core/lib'));
+    $namespaces = drupal_classloader()->getNamespaces();
+    foreach ($namespaces as $ns => $namespace_dirs) {
+      $ns = str_replace('\\', DIRECTORY_SEPARATOR, $ns);
+      foreach ($namespace_dirs as $dir) {
+        $prefix = implode(DIRECTORY_SEPARATOR, array(
+          $ns,
+          'Plugin',
+          $this->owner,
+          $this->type
+        ));
+        $dir .= DIRECTORY_SEPARATOR . $prefix;
+        if (file_exists($dir)) {
+          $directories = new DirectoryIterator($dir);
+          foreach ($directories as $fileinfo) {
+            if ($fileinfo->getExtension() == 'php') {
+              $className = str_replace(DIRECTORY_SEPARATOR, '\\', "$prefix/". $fileinfo->getBasename('.php'));
+              $staticReflectionParser = new StaticReflectionParser($className, new Psr0FindFile($namespaces));
+              if ($annotation = $reader->getClassAnnotation($staticReflectionParser->getReflectionClass(), 'Drupal\Core\Annotation\Plugin')) {
+                $definition = $annotation->get();
+                $definition['class'] = $reflectionClass->name;
+                $definitions[$definition['plugin_id']] = $definition;
+              }
+            }
+          }
+        }
+      }
+    }
+    return $definitions;
+  }
+}
+
diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module
index 723de86..047026a 100644
--- a/core/modules/aggregator/aggregator.module
+++ b/core/modules/aggregator/aggregator.module
@@ -801,19 +801,6 @@ function _aggregator_items($count) {
 }
 
 /**
- * Implements hook_aggregator_fetch_info().
- */
-function aggregator_aggregator_fetch_info() {
-  return array(
-    'aggregator' => array(
-      'class' => 'Drupal\aggregator\Plugin\aggregator\fetcher\DefaultFetcher',
-      'title' => t('Default fetcher'),
-      'description' => t('Downloads data from a URL using Drupal\'s HTTP request handler.'),
-    ),
-  );
-}
-
-/**
  * Implements hook_preprocess_HOOK() for block.tpl.php.
  */
 function aggregator_preprocess_block(&$variables) {
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/FetcherManager.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/FetcherManager.php
index ae24934..a95fc33 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/FetcherManager.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/FetcherManager.php
@@ -8,7 +8,7 @@
 namespace Drupal\aggregator\Plugin;
 
 use Drupal\Component\Plugin\PluginManagerBase;
-use Drupal\Core\Plugin\Discovery\HookDiscovery;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 
 /**
@@ -17,7 +17,7 @@ use Drupal\Component\Plugin\Factory\DefaultFactory;
 class FetcherManager extends PluginManagerBase {
 
   public function __construct() {
-    $this->discovery = new HookDiscovery('aggregator_fetch_info');
+    $this->discovery = new AnnotatedClassDiscovery('aggregator', 'fetcher');
     $this->factory = new DefaultFactory($this->discovery);
   }
 }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
index e4b663b..3f559a4 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
@@ -8,12 +8,22 @@
 namespace Drupal\aggregator\Plugin\aggregator\fetcher;
 
 use Drupal\aggregator\Plugin\FetcherInterface;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
 
 /**
  * Defines a default fetcher implementation.
  *
  * Uses drupal_http_request() to download the feed.
  */
+
+/**
+ * @Plugin(
+ *   plugin_id = "aggregator",
+ *   title = @Translation("Default fetcher"),
+ *   description = @Translation("Downloads data from a URL using Drupal's HTTP request handler.")
+ * )
+ */
 class DefaultFetcher implements FetcherInterface {
 
   /**
