diff --git a/core/core.events.yml b/core/core.events.yml
new file mode 100644
index 0000000..4878546
--- /dev/null
+++ b/core/core.events.yml
@@ -0,0 +1,88 @@
+subscribers:
+  config.importer.import:
+    - callback: config_snapshot_subscriber:onConfigImporterImport
+      priority: 40
+  config.importer.validate:
+    - callback: Drupal\Core\EventSubscriber\ConfigImportSubscriber::onConfigImporterValidate
+      priority: 40
+  config.save:
+    - callback: config.factory:onConfigSave
+      priority: 255
+  kernel.request:
+    - callback: path_subscriber:onKernelRequestConvertPath
+      priority: 200
+    - callback: Drupal\Core\EventSubscriber\LegacyRequestSubscriber::onKernelRequestLegacy
+      priority: 90
+    - callback: Drupal\Core\Ajax\AjaxSubscriber::onKernelRequest
+      priority: 50
+    - callback: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber::onKernelRequestDetermineSiteStatus
+      priority: 40
+    - callback: router_listener:onKernelRequest
+      priority: 32
+    - callback: route_content_controller_subscriber:onRequestDeriveFormat
+      priority: 31
+    - callback: route_content_controller_subscriber:onRequestDeriveContentWrapper
+      priority: 30
+    - callback: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber::onKernelRequestMaintenance
+      priority: 30
+    - callback: Drupal\Core\EventSubscriber\LegacyRequestSubscriber::onKernelRequestLegacyAfterRouting
+      priority: 30
+    - callback: access_subscriber:onKernelRequestAccessCheck
+      priority: 30
+    - callback: route_content_form_controller_subscriber:onRequestDeriveFormWrapper
+      priority: 29
+    - callback: reverse_proxy_subscriber:onKernelRequestReverseProxyCheck
+      priority: 10
+    - slave_database_ignore__subscriber:checkSlaveServer
+    - router.route_preloader:onRequest
+  kernel.response:
+    - finish_response_subscriber:onRespond
+    - redirect_response_subscriber:checkRedirectUrl
+    - authentication_subscriber:onRespond
+    - callback: Drupal\Core\EventSubscriber\AjaxResponseSubscriber::onResponse
+      priority: -100
+  kernel.exception:
+    - callback: exception_listener:onKernelException
+      priority: -128
+    - authentication_subscriber:onException
+    - route_enhancer.param_conversion:onException
+  kernel.view:
+    - callback: html_view_subscriber:onHtmlFragment
+      priority: 100
+    - callback: html_view_subscriber:onHtmlPage
+      priority: 50
+    - view_subscriber:onView
+  kernel.finish_request:
+    - router_listener:onKernelFinishRequest
+  kernel.terminate:
+    - callback: path_subscriber:onKernelTerminate
+      priority: 200
+    - callback: request_close_subscriber:onTerminate
+      priority: 100
+    - callback: kernel_destruct_subscriber:onKernelTerminate
+      priority: 100
+    - callback: router.rebuild_subscriber:onKernelTerminate
+      priority: 200
+  routing.route_alter:
+    - callback: Drupal\Core\EventSubscriber\RouteMethodSubscriber::onRouteBuilding
+      priority: 5000
+    - route_subscriber.module:onAlterRoutes
+    - Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber::onAlterRoutes
+    - callback: route_subscriber.entity:onRoutingRouteAlterSetType
+      priority: -150
+    - callback: paramconverter_subscriber:onRoutingRouteAlterSetParameterConverters
+      priority: -210
+    - callback: access_route_subscriber:onRoutingRouteAlterSetAccessCheck
+      # Setting very low priority to ensure access checks are run after alters.
+      priority: -1000
+      # Set a really low priority to catch as many as possible routes.
+    - callback: router.route_preloader:onAlterRoutes
+      priority: -1024
+    - callback: router.path_roots_subscriber:onRouteAlter
+      priority: -1024
+  routing.route_finished:
+    - router.route_provider:reset
+    - router.route_preloader:onFinishedRoutes
+    - router.path_roots_subscriber:onRouteFinished
+    - callback: router.rebuild_subscriber:onRouterRebuild
+      priority: 200
diff --git a/core/core.services.yml b/core/core.services.yml
index 951c458..299bcf9 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -86,7 +86,6 @@ services:
   config.factory:
     class: Drupal\Core\Config\ConfigFactory
     tags:
-      - { name: event_subscriber }
       - { name: service_collector, tag: 'config.factory.override', call: addOverride }
     arguments: ['@config.storage', '@event_dispatcher', '@config.typed']
   config.installer:
@@ -318,13 +317,9 @@ services:
   router.route_provider:
     class: Drupal\Core\Routing\RouteProvider
     arguments: ['@database', '@router.builder', '@state']
-    tags:
-      - { name: event_subscriber }
   router.route_preloader:
     class: Drupal\Core\Routing\RoutePreloader
     arguments: ['@router.route_provider', '@state', '@content_negotiation']
-    tags:
-      - { name: 'event_subscriber' }
   router.matcher.final_matcher:
     class: Drupal\Core\Routing\UrlMatcher
   router.matcher:
@@ -356,8 +351,6 @@ services:
   router.path_roots_subscriber:
     class: Drupal\Core\EventSubscriber\PathRootsSubscriber
     arguments: ['@state']
-    tags:
-      - { name: event_subscriber }
   entity.query:
     class: Drupal\Core\Entity\Query\QueryFactory
     arguments: ['@entity.manager']
@@ -381,8 +374,6 @@ services:
   router.rebuild_subscriber:
     class: Drupal\Core\EventSubscriber\RouterRebuildSubscriber
     arguments: ['@router.builder', '@lock']
-    tags:
-      - { name: event_subscriber }
   path.alias_manager.cached:
     class: Drupal\Core\CacheDecorator\AliasManagerCacheDecorator
     arguments: ['@path.alias_manager', '@cache.data']
@@ -413,8 +404,6 @@ services:
       - [setContainer, ['@service_container']]
   paramconverter_subscriber:
     class: Drupal\Core\EventSubscriber\ParamConverterSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@paramconverter_manager']
   paramconverter.entity:
     class: Drupal\Core\ParamConverter\EntityConverter
@@ -429,29 +418,18 @@ services:
     arguments: ['@entity.manager', '@config.factory', '@router.admin_context']
   route_subscriber.module:
     class: Drupal\Core\EventSubscriber\ModuleRouteSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@module_handler']
   route_subscriber.entity:
     class: Drupal\Core\EventSubscriber\EntityRouteAlterSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@entity.manager']
   reverse_proxy_subscriber:
     class: Drupal\Core\EventSubscriber\ReverseProxySubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@settings']
-  ajax_response_subscriber:
-    class: Drupal\Core\EventSubscriber\AjaxResponseSubscriber
-    tags:
-      - { name: event_subscriber }
   route_enhancer.param_conversion:
     class: Drupal\Core\Routing\Enhancer\ParamConversionEnhancer
     arguments: ['@paramconverter_manager']
     tags:
       - { name: route_enhancer }
-      - { name: event_subscriber }
   route_enhancer.authentication:
     class: Drupal\Core\Routing\Enhancer\AuthenticationEnhancer
     tags:
@@ -465,22 +443,10 @@ services:
   route_content_controller_subscriber:
     class: Drupal\Core\EventSubscriber\ContentControllerSubscriber
     arguments: ['@content_negotiation']
-    tags:
-      - { name: event_subscriber }
   route_content_form_controller_subscriber:
     class: Drupal\Core\EventSubscriber\ContentFormControllerSubscriber
     arguments: ['@controller_resolver', '@form_builder']
     parent: container.trait
-    tags:
-      - { name: event_subscriber }
-  route_special_attributes_subscriber:
-    class: Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber
-    tags:
-      - { name: event_subscriber }
-  route_http_method_subscriber:
-    class: Drupal\Core\EventSubscriber\RouteMethodSubscriber
-    tags:
-      - { name: event_subscriber }
   controller.page:
     class: Drupal\Core\Controller\HtmlPageController
     arguments: ['@controller_resolver', '@title_resolver']
@@ -497,20 +463,14 @@ services:
     class: Drupal\Core\Ajax\AjaxResponseRenderer
   router_listener:
     class: Symfony\Component\HttpKernel\EventListener\RouterListener
-    tags:
-      - { name: event_subscriber }
     arguments: ['@router', '@router.request_context', NULL, '@request_stack']
   content_negotiation:
     class: Drupal\Core\ContentNegotiation
   view_subscriber:
     class: Drupal\Core\EventSubscriber\ViewSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@content_negotiation', '@title_resolver', '@ajax_response_renderer']
   html_view_subscriber:
     class: Drupal\Core\EventSubscriber\HtmlViewSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@html_fragment_renderer', '@html_page_renderer']
   html_fragment_renderer:
     class: Drupal\Core\Page\DefaultHtmlFragmentRenderer
@@ -534,12 +494,8 @@ services:
     arguments: ['@access_manager', '@current_user']
     calls:
       - [setCurrentUser, ['@?current_user']]
-    tags:
-      - { name: event_subscriber }
   access_route_subscriber:
     class: Drupal\Core\EventSubscriber\AccessRouteSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@access_manager']
   access_check.default:
     class: Drupal\Core\Access\DefaultAccessCheck
@@ -568,44 +524,24 @@ services:
     tags:
       - { name: access_check, applies_to: _csrf_token }
     arguments: ['@csrf_token']
-  maintenance_mode_subscriber:
-    class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber
-    tags:
-      - { name: event_subscriber }
   path_subscriber:
     class: Drupal\Core\EventSubscriber\PathSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@path.alias_manager.cached', '@path_processor_manager']
   legacy_request_subscriber:
     class: Drupal\Core\EventSubscriber\LegacyRequestSubscriber
-    tags:
-      - { name: event_subscriber }
   finish_response_subscriber:
     class: Drupal\Core\EventSubscriber\FinishResponseSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@language_manager']
     scope: request
   redirect_response_subscriber:
     class: Drupal\Core\EventSubscriber\RedirectResponseSubscriber
     arguments: ['@url_generator']
-    tags:
-      - { name: event_subscriber }
     scope: request
   request_close_subscriber:
     class: Drupal\Core\EventSubscriber\RequestCloseSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@module_handler']
-  config_import_subscriber:
-    class: Drupal\Core\EventSubscriber\ConfigImportSubscriber
-    tags:
-      - { name: event_subscriber }
   config_snapshot_subscriber:
     class: Drupal\Core\EventSubscriber\ConfigSnapshotSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@config.manager', '@config.storage', '@config.storage.snapshot']
   exception_controller:
     class: Drupal\Core\Controller\ExceptionController
@@ -614,8 +550,6 @@ services:
       - [setContainer, ['@service_container']]
   exception_listener:
     class: Drupal\Core\EventSubscriber\ExceptionListener
-    tags:
-      - { name: event_subscriber }
     arguments: [['@exception_controller', execute]]
   route_processor_manager:
     class: Drupal\Core\RouteProcessor\RouteProcessorManager
@@ -660,14 +594,8 @@ services:
     parent: default_plugin_manager
   kernel_destruct_subscriber:
     class: Drupal\Core\EventSubscriber\KernelDestructionSubscriber
-    tags:
-      - { name: event_subscriber }
     calls:
       - [setContainer, ['@service_container']]
-  ajax.subscriber:
-    class: Drupal\Core\Ajax\AjaxSubscriber
-    tags:
-      - { name: event_subscriber }
   image.toolkit.manager:
     class: Drupal\Core\ImageToolkit\ImageToolkitManager
     arguments: ['@container.namespaces', '@cache.discovery', '@language_manager', '@config.factory', '@module_handler']
@@ -687,8 +615,6 @@ services:
     arguments: ['@database']
   slave_database_ignore__subscriber:
     class: Drupal\Core\EventSubscriber\SlaveDatabaseIgnoreSubscriber
-    tags:
-      - {name: event_subscriber}
   country_manager:
     class: Drupal\Core\Locale\CountryManager
     arguments: ['@module_handler']
@@ -763,8 +689,6 @@ services:
       - { name: authentication_provider, priority: 0 }
   authentication_subscriber:
     class: Drupal\Core\EventSubscriber\AuthenticationSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@authentication']
   current_user:
     class: Drupal\Core\Session\AccountProxy
diff --git a/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php b/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php
index f298d88..06d0da0 100644
--- a/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php
+++ b/core/lib/Drupal/Core/Ajax/AjaxSubscriber.php
@@ -7,9 +7,7 @@
 
 namespace Drupal\Core\Ajax;
 
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Subscribes to the kernel request event to add the Ajax media type.
@@ -17,7 +15,7 @@
  * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
  *   The event to process.
  */
-class AjaxSubscriber implements EventSubscriberInterface {
+class AjaxSubscriber {
 
   /**
    * Registers Ajax formats with the Request class.
@@ -29,15 +27,4 @@ public function onKernelRequest(GetResponseEvent $event) {
     $request->setFormat('drupal_modal', 'application/vnd.drupal-modal');
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents(){
-    $events[KernelEvents::REQUEST][] = array('onKernelRequest', 50);
-    return $events;
-  }
-
 }
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php
index 5d3756e..971d212 100644
--- a/core/lib/Drupal/Core/Config/ConfigFactory.php
+++ b/core/lib/Drupal/Core/Config/ConfigFactory.php
@@ -24,7 +24,7 @@
  *
  * @see \Drupal\Core\Config\StorageInterface
  */
-class ConfigFactory implements ConfigFactoryInterface, EventSubscriberInterface {
+class ConfigFactory implements ConfigFactoryInterface {
 
   /**
    * A storage instance for reading and writing configuration data.
@@ -300,14 +300,6 @@ public function onConfigSave(ConfigCrudEvent $event) {
   /**
    * {@inheritdoc}
    */
-  static function getSubscribedEvents() {
-    $events[ConfigEvents::SAVE][] = array('onConfigSave', 255);
-    return $events;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function addOverride(ConfigFactoryOverrideInterface $config_factory_override) {
     $this->configFactoryOverrides[] = $config_factory_override;
   }
diff --git a/core/lib/Drupal/Core/Config/ConfigImportValidateEventSubscriberBase.php b/core/lib/Drupal/Core/Config/ConfigImportValidateEventSubscriberBase.php
index ee5340c..ac18896 100644
--- a/core/lib/Drupal/Core/Config/ConfigImportValidateEventSubscriberBase.php
+++ b/core/lib/Drupal/Core/Config/ConfigImportValidateEventSubscriberBase.php
@@ -8,12 +8,11 @@
 namespace Drupal\Core\Config;
 
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Defines a base event listener implementation for config sync validation.
  */
-abstract class ConfigImportValidateEventSubscriberBase implements EventSubscriberInterface {
+abstract class ConfigImportValidateEventSubscriberBase {
   use StringTranslationTrait;
 
   /**
@@ -24,12 +23,4 @@
    */
   abstract public function onConfigImporterValidate(ConfigImporterEvent $event);
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[ConfigEvents::IMPORT_VALIDATE][] = array('onConfigImporterValidate', 20);
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index 11c7781..f1799cd 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -60,6 +60,7 @@ public function register(ContainerBuilder $container) {
     // Add a compiler pass for registering event subscribers.
     $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
 
+    $container->addCompilerPass(new EventListenerPass(), PassConfig::TYPE_AFTER_REMOVING);
     $container->addCompilerPass(new RegisterAccessChecksPass());
 
     // Add a compiler pass for upcasting route parameters.
diff --git a/core/lib/Drupal/Core/EventListenerPass.php b/core/lib/Drupal/Core/EventListenerPass.php
new file mode 100644
index 0000000..a107396
--- /dev/null
+++ b/core/lib/Drupal/Core/EventListenerPass.php
@@ -0,0 +1,228 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\EventListenerPass
+ */
+
+namespace Drupal\Core;
+
+use Drupal\Component\Discovery\YamlDiscovery;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Defines a listener to register listeners defined in .events.yml files.
+ *
+ * These yml files contains a list of callbacks keyed by the event name, for
+ * example kernel.request.
+ *
+ * Each callback can be either a class, method or service, method combination.
+ * Services uses a single colon, classes two.
+ *
+ * @code
+ *   kernel.request:
+ *     - Drupal\user\EventSubscriber\MaintenanceModeSubscriber::onKernelRequestMaintenance
+ *     - access_subscriber:onKernelRequestAccessCheck
+ * @endcode
+ *
+ * Additionally you can also specify a priority:
+ *
+ * @code
+ *   kernel.request:
+ *     - callback: Drupal\user\EventSubscriber\MaintenanceModeSubscriber::onKernelRequestMaintenance
+ *       priority: 14
+ *     - callback: access_subscriber:onKernelRequestAccessCheck
+ *       priority: 95
+ * @endcode
+ */
+class EventListenerPass implements CompilerPassInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function process(ContainerBuilder $container) {
+    if (!$container->hasDefinition('event_dispatcher')) {
+      return;
+    }
+
+    $event_dispatcher_definition = $container->getDefinition('event_dispatcher');
+    $module_handler = $container->get('module_handler');
+
+    $this->findListeners($container, $event_dispatcher_definition, $module_handler);
+  }
+
+  /**
+   * Find the event listeners in event.yml files and add it to the container.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *   The container to add event services to.
+   * @param \Symfony\Component\DependencyInjection\Definition $event_dispatcher_definition
+   *   The event dispatcher service definition.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to get the module directories from.
+   */
+  protected function findListeners(ContainerBuilder $container, Definition $event_dispatcher_definition, ModuleHandlerInterface $module_handler) {
+    foreach ($this->getYamlDiscovery($module_handler)->findAll() as $info) {
+      foreach ((array) $info['subscribers'] as $event_id => $listeners) {
+        foreach ((array) $listeners as $listener) {
+          if ($result = $this->prepareListener($container, $event_id, $listener)) {
+            list($add_method, $args) = $result;
+            $event_dispatcher_definition->addMethodCall($add_method, $args);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Creates the needed listener information to pass onto the event dispatcher.
+   *
+   * This method uses a single listener information, determines whether it is
+   * a service, method or just class, method.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *   The container to add event services to.
+   * @param string $event_id
+   *   The used event.
+   * @param array $listener
+   *   The parsed listener array.
+   *
+   * @return array
+   *   An array containing 'addListenerService' and the needed arguments for
+   *   $definition->addMethodCall.
+   */
+  protected function prepareListener(ContainerBuilder $container, $event_id, $listener) {
+    if (is_array($listener)) {
+      $callback = $listener['callback'];
+      if (isset($listener['priority'])) {
+        $priority = $listener['priority'];
+      }
+    }
+    else {
+      $callback = $listener;
+    }
+
+    if (!($callback_parts = $this->parseCallback($callback, $container))) {
+      return;
+    }
+    $method = $callback_parts['method'];
+
+    if (isset($callback_parts['class'])) {
+      $callback_parts['service'] = $this->defineService($container, $callback_parts['class']);
+    }
+    $args = array($event_id, array($callback_parts['service'], $method));
+    $add_method = 'addListenerService';
+
+    if (isset($priority)) {
+      $args[] = $priority;
+    }
+    return array($add_method, $args);
+  }
+
+  /**
+   * Registers a new service without any dependency.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *   The container builder.
+   *
+   * @param string $class
+   *   The class of the new service.
+   *
+   * @return string
+   *   The name of the new service.
+   */
+  protected function defineService(ContainerBuilder $container, $class) {
+    $definition = new Definition();
+    $definition->setClass($class);
+    $name = 'event_listener.' . str_replace("\\", '.', $class);
+    $container->setDefinition($name, $definition);
+    return $name;
+  }
+
+  /**
+   * Parses a single callback and converts it a php array.
+   *
+   * @param string $callback
+   *   The listener string which is part of the events.yml file.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *   The container builder.
+   *
+   * @throws \UnexpectedValueException
+   *   Thrown when the callback could not be parsed.
+   * @throws \InvalidArgumentException
+   *   Thrown when the class/service does not exists.
+   *
+   * @return array
+   *   An array with the following keys:
+   *   - service: The name of the service of the listener OR
+   *   - class: The name of the class of the listener
+   *   - method: The method name of the listener
+   */
+  protected function parseCallback($callback, ContainerBuilder $container) {
+    // @TODO: Maybe use https://drupal.org/node/2165475 instead.
+    $optional = $callback[0] == '?';
+
+    // Callback in the service:method notation.
+    $count = substr_count($callback, ':');
+    if ($count == 1) {
+      list($service, $method) = explode(':', $callback, 2);
+      if ($optional) {
+        $service = substr($service, 1);
+      }
+
+      if (!$container->has($service)) {
+        if ($optional) {
+          return array();
+        }
+        else {
+          throw new \InvalidArgumentException(sprintf('Service "%s" does not exist.', $service));
+        }
+      }
+
+      return array('service' => $service, 'method' => $method);
+    }
+
+    // Callback in the class::method notation.
+    if (strpos($callback, '::') !== FALSE) {
+      list($class, $method) = explode('::', $callback, 2);
+      if ($optional) {
+        $class = substr($class, 1);
+      }
+
+      if (!class_exists($class)) {
+        if ($optional) {
+          return array();
+        }
+        else {
+          throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
+        }
+      }
+      return array('class' => $class, 'method' => $method);
+    }
+    else {
+      throw new \UnexpectedValueException(sprintf('Unable to parse the callback name "%s".', $callback));
+    }
+  }
+
+  /**
+   * Returns the YAML discovery for getting all the .routing.yml files.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   *
+   * @return \Drupal\Component\Discovery\YamlDiscovery
+   *   The yaml discovery.
+   */
+  protected function getYamlDiscovery(ModuleHandlerInterface $module_handler) {
+    if (!isset($this->yamlDiscovery)) {
+      $this->yamlDiscovery = new YamlDiscovery('events', array('core' => DRUPAL_ROOT . '/core') + $module_handler->getModuleDirectories());
+    }
+    return $this->yamlDiscovery;
+  }
+
+}
+
diff --git a/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php
index dee7d32..61999a5 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php
@@ -9,13 +9,11 @@
 
 use Drupal\Core\Access\AccessManager;
 use Drupal\Core\Routing\RouteBuildEvent;
-use Drupal\Core\Routing\RoutingEvents;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Provides a subscriber to set access checkers on route building.
  */
-class AccessRouteSubscriber implements EventSubscriberInterface {
+class AccessRouteSubscriber {
 
   /**
    * The access manager.
@@ -45,17 +43,4 @@ public function onRoutingRouteAlterSetAccessCheck(RouteBuildEvent $event) {
     $this->accessManager->setChecks($event->getRouteCollection());
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    // Setting very low priority to ensure access checks are run after alters.
-    $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetAccessCheck', -1000);
-
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php
index 0c31999..4f2aecb 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php
@@ -10,16 +10,13 @@
 use Drupal\Core\Access\AccessManager;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
 /**
  * Access subscriber for controller requests.
  */
-class AccessSubscriber implements EventSubscriberInterface {
+class AccessSubscriber {
 
   /**
    * The current user.
@@ -98,16 +95,4 @@ public function setCurrentUser(AccountInterface $current_user = NULL) {
     $this->currentUser = $current_user;
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestAccessCheck', 30);
-
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
index cf4dca1..1fe3a6a 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AjaxResponseSubscriber.php
@@ -8,12 +8,9 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\Ajax\AjaxResponse;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
 
-class AjaxResponseSubscriber implements EventSubscriberInterface {
+class AjaxResponseSubscriber {
 
   /**
    * Renders the ajax commands right before preparing the result.
@@ -28,13 +25,4 @@ public function onResponse(FilterResponseEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::RESPONSE][] = array('onResponse', -100);
-
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
index 87a3cfe..25bae2d 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
@@ -9,17 +9,15 @@
 
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Authentication subscriber.
  *
  * Trigger authentication and cleanup during the request.
  */
-class AuthenticationSubscriber implements EventSubscriberInterface {
+class AuthenticationSubscriber {
 
   /**
    * Authentication provider.
@@ -61,17 +59,4 @@ public function onException(GetResponseForExceptionEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   *
-   * The priority for request must be higher than the highest event subscriber
-   * accessing the current user.
-   * The priority for the response must be as low as possible allowing e.g the
-   * Cookie provider to send all relevant session data to the user.
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::RESPONSE][] = array('onRespond', 0);
-    $events[KernelEvents::EXCEPTION][] = array('onException', 0);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/ConfigSnapshotSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ConfigSnapshotSubscriber.php
index a8d0e06..0cff3b0 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ConfigSnapshotSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ConfigSnapshotSubscriber.php
@@ -16,7 +16,7 @@
 /**
  * Create a snapshot when config is imported.
  */
-class ConfigSnapshotSubscriber implements EventSubscriberInterface {
+class ConfigSnapshotSubscriber {
 
   /**
    * The configuration manager.
@@ -63,15 +63,4 @@ public function onConfigImporterImport(ConfigImporterEvent $event) {
     $this->configManager->createSnapshot($this->sourceStorage, $this->snapshotStorage);
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[ConfigEvents::IMPORT][] = array('onConfigImporterImport', 40);
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php
index 377ae93..0bab1ff 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ContentControllerSubscriber.php
@@ -15,7 +15,7 @@
 /**
  * Defines a subscriber for setting the format of the request.
  */
-class ContentControllerSubscriber implements EventSubscriberInterface {
+class ContentControllerSubscriber {
 
   /**
    * Content negotiation library.
@@ -77,17 +77,4 @@ public function onRequestDeriveContentWrapper(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onRequestDeriveFormat', 31);
-    $events[KernelEvents::REQUEST][] = array('onRequestDeriveContentWrapper', 30);
-
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php
index b64e6a4..d1c8cff 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ContentFormControllerSubscriber.php
@@ -11,15 +11,13 @@
 use Drupal\Core\Controller\ControllerResolverInterface;
 use Drupal\Core\Form\FormBuilderInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 
 /**
  * Subscriber for setting wrapping form logic.
  */
-class ContentFormControllerSubscriber implements EventSubscriberInterface, ContainerAwareInterface {
+class ContentFormControllerSubscriber implements ContainerAwareInterface {
 
   use ContainerAwareTrait;
 
@@ -65,15 +63,4 @@ public function onRequestDeriveFormWrapper(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onRequestDeriveFormWrapper', 29);
-
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/EntityRouteAlterSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/EntityRouteAlterSubscriber.php
index 6283dae..dcefa99 100644
--- a/core/lib/Drupal/Core/EventSubscriber/EntityRouteAlterSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/EntityRouteAlterSubscriber.php
@@ -8,7 +8,6 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\Entity\EntityManagerInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Drupal\Core\Routing\RoutingEvents;
 use Drupal\Core\Routing\RouteBuildEvent;
 
@@ -23,7 +22,7 @@
  *   kind of PHP variable (e.g., a type hinted interface) the controller
  *   requires: https://drupal.org/node/2041907.
  */
-class EntityRouteAlterSubscriber implements EventSubscriberInterface {
+class EntityRouteAlterSubscriber {
 
   /**
    * Entity manager.
@@ -68,11 +67,4 @@ public function onRoutingRouteAlterSetType(RouteBuildEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetType', -150);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 8e4596f..0fbd04a 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -10,14 +10,12 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Response subscriber to handle finished responses.
  */
-class FinishResponseSubscriber implements EventSubscriberInterface {
+class FinishResponseSubscriber {
 
   /**
    * The LanguageManager object for retrieving the correct language code.
@@ -110,14 +108,4 @@ public function onRespond(FilterResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::RESPONSE][] = array('onRespond');
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php
index 36f2891..0c197e2 100644
--- a/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/HtmlViewSubscriber.php
@@ -19,7 +19,7 @@
 /**
  * Main subscriber for Html-page responses.
  */
-class HtmlViewSubscriber implements EventSubscriberInterface {
+class HtmlViewSubscriber {
 
   /**
    * The fragment rendering service.
@@ -93,19 +93,6 @@ public function onHtmlPage(GetResponseForControllerResultEvent $event) {
   }
 
   /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::VIEW][] = array('onHtmlFragment', 100);
-    $events[KernelEvents::VIEW][] = array('onHtmlPage', 50);
-
-    return $events;
-  }
-
-  /**
    * Converts a cache tags array into a X-Drupal-Cache-Tags header value.
    *
    * @param array $tags
diff --git a/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php
index 7cedb1c..884cf3b 100644
--- a/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php
@@ -8,14 +8,12 @@
 namespace Drupal\Core\EventSubscriber;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\PostResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Destructs services that are initiated and tagged with "needs_destruction".
  */
-class KernelDestructionSubscriber implements EventSubscriberInterface, ContainerAwareInterface {
+class KernelDestructionSubscriber implements ContainerAwareInterface {
 
   use ContainerAwareTrait;
   /**
@@ -55,14 +53,4 @@ public function onKernelTerminate(PostResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::TERMINATE][] = array('onKernelTerminate', 100);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
index 8c75e7b..df1b0f0 100644
--- a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php
@@ -19,7 +19,7 @@
 /**
  * Maintenance mode subscriber for controller requests.
  */
-class MaintenanceModeSubscriber implements EventSubscriberInterface {
+class MaintenanceModeSubscriber {
 
   /**
    * Determine whether the page is configured to be offline.
@@ -57,14 +57,4 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    // In order to change the maintenance status an event subscriber with a
-    // priority between 30 and 40 should be added.
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestDetermineSiteStatus', 40);
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestMaintenance', 30);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php.rej b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php.rej
new file mode 100644
index 0000000..a1938c3
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php.rej
@@ -0,0 +1,17 @@
+diff a/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/MaintenanceModeSubscriber.php	(rejected hunks)
+@@ -11,14 +11,12 @@
+ use Drupal\Core\Page\DefaultHtmlPageRenderer;
+ use Symfony\Component\HttpFoundation\RedirectResponse;
+ use Symfony\Component\HttpFoundation\Response;
+-use Symfony\Component\HttpKernel\KernelEvents;
+ use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+ /**
+  * Maintenance mode subscriber for controller requests.
+  */
+-class MaintenanceModeSubscriber implements EventSubscriberInterface {
++class MaintenanceModeSubscriber {
+
+   /**
+    * Determine whether the page is configured to be offline.
diff --git a/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
index eba4003..c4f453d 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ParamConverterSubscriber.php
@@ -8,14 +8,12 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\ParamConverter\ParamConverterManagerInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Drupal\Core\Routing\RoutingEvents;
 use Drupal\Core\Routing\RouteBuildEvent;
 
 /**
  * Event subscriber for registering parameter converters with routes.
  */
-class ParamConverterSubscriber implements EventSubscriberInterface {
+class ParamConverterSubscriber {
 
   /**
    * The parameter converter manager.
@@ -45,12 +43,4 @@ public function onRoutingRouteAlterSetParameterConverters(RouteBuildEvent $event
     $this->paramConverterManager->setRouteParameterConverters($event->getRouteCollection());
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    // Run after \Drupal\system\EventSubscriber\AdminRouteSubscriber.
-    $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetParameterConverters', -210);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
index 8d96767..90608a4 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
@@ -9,14 +9,12 @@
 
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Routing\RouteBuildEvent;
-use Drupal\Core\Routing\RoutingEvents;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Symfony\Component\Routing\RouteCollection;
 
 /**
  * Provides all available first bits of all route paths.
  */
-class PathRootsSubscriber implements EventSubscriberInterface {
+class PathRootsSubscriber {
 
   /**
    * Stores the path roots available in the router.
@@ -67,15 +65,4 @@ public function onRouteFinished() {
     unset($this->pathRoots);
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events = array();
-    // Try to set a low priority to ensure that all routes are already added.
-    $events[RoutingEvents::ALTER][] = array('onRouteAlter', -1024);
-    $events[RoutingEvents::FINISHED][] = array('onRouteFinished');
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
index 21a0c62..d2a5f0e 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
@@ -10,15 +10,13 @@
 use Drupal\Core\Path\AliasManagerInterface;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\HttpKernel\Event\PostResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Provides a path subscriber that converts path aliases.
  */
-class PathSubscriber extends PathListenerBase implements EventSubscriberInterface {
+class PathSubscriber extends PathListenerBase {
 
   /**
    * The alias manager that caches alias lookups based on the request.
@@ -64,15 +62,4 @@ public function onKernelTerminate(PostResponseEvent $event) {
     $this->aliasManager->writeCache();
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestConvertPath', 200);
-    $events[KernelEvents::TERMINATE][] = array('onKernelTerminate', 200);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
index c7687fa..0395d05 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
@@ -9,16 +9,13 @@
 
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Routing\UrlGeneratorInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
-use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
 use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Allows manipulation of the response object when performing a redirect.
  */
-class RedirectResponseSubscriber implements EventSubscriberInterface {
+class RedirectResponseSubscriber {
 
   /**
    * The url generator service.
@@ -40,7 +37,7 @@ public function __construct(UrlGeneratorInterface $url_generator) {
   /**
    * Allows manipulation of the response object when performing a redirect.
    *
-   * @param Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
    *   The Event to process.
    */
   public function checkRedirectUrl(FilterResponseEvent $event) {
@@ -69,14 +66,4 @@ public function checkRedirectUrl(FilterResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::RESPONSE][] = array('checkRedirectUrl');
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php
index 1422a83..c751816 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php
@@ -8,14 +8,12 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\PostResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Subscriber for all responses.
  */
-class RequestCloseSubscriber implements EventSubscriberInterface {
+class RequestCloseSubscriber {
 
   /**
    * @var \Drupal\Core\Extension\ModuleHandlerInterface
@@ -44,15 +42,4 @@ public function onTerminate(PostResponseEvent $event) {
     $this->moduleHandler->writeCache();
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
-
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/ReverseProxySubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ReverseProxySubscriber.php
index 788076a..4e3a68e 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ReverseProxySubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ReverseProxySubscriber.php
@@ -8,14 +8,12 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Reverse proxy subscriber for controller requests.
  */
-class ReverseProxySubscriber implements EventSubscriberInterface {
+class ReverseProxySubscriber {
 
   /**
    * A settings object.
@@ -50,14 +48,4 @@ public function onKernelRequestReverseProxyCheck(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestReverseProxyCheck', 10);
-    return $events;
-  }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php
index 98bf05c..776f87c 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RouterRebuildSubscriber.php
@@ -10,16 +10,14 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Lock\LockBackendInterface;
 use Drupal\Core\Routing\RouteBuilderInterface;
-use Drupal\Core\Routing\RoutingEvents;
 use Symfony\Component\EventDispatcher\Event;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\PostResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Rebuilds the default menu links and runs menu-specific code if necessary.
  */
-class RouterRebuildSubscriber implements EventSubscriberInterface {
+class RouterRebuildSubscriber {
 
   /**
    * @var \Drupal\Core\Routing\RouteBuilderInterface
@@ -93,16 +91,4 @@ protected function menuLinksRebuild() {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::TERMINATE][] = array('onKernelTerminate', 200);
-    $events[RoutingEvents::FINISHED][] = array('onRouterRebuild', 200);
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/SlaveDatabaseIgnoreSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/SlaveDatabaseIgnoreSubscriber.php
index e10ce04..4568adc 100644
--- a/core/lib/Drupal/Core/EventSubscriber/SlaveDatabaseIgnoreSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/SlaveDatabaseIgnoreSubscriber.php
@@ -8,14 +8,12 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Core\Database\Database;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * System subscriber for controller requests.
  */
-class SlaveDatabaseIgnoreSubscriber implements EventSubscriberInterface {
+class SlaveDatabaseIgnoreSubscriber {
 
   /**
    * Checks and disables the slave database server if appropriate.
@@ -49,12 +47,4 @@ public function checkSlaveServer(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('checkSlaveServer');
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php b/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
index 614ac96..7e5698e 100644
--- a/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
+++ b/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
@@ -16,12 +16,11 @@
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Provides a route enhancer that handles parameter conversion.
  */
-class ParamConversionEnhancer implements RouteEnhancerInterface, EventSubscriberInterface {
+class ParamConversionEnhancer implements RouteEnhancerInterface {
 
   /**
    * The parameter conversion manager.
@@ -82,12 +81,4 @@ public function onException(GetResponseForExceptionEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::EXCEPTION][] = array('onException', 0);
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Routing/RoutePreloader.php b/core/lib/Drupal/Core/Routing/RoutePreloader.php
index 7952d17..ba16445 100644
--- a/core/lib/Drupal/Core/Routing/RoutePreloader.php
+++ b/core/lib/Drupal/Core/Routing/RoutePreloader.php
@@ -10,9 +10,7 @@
 use Drupal\Core\ContentNegotiation;
 use Drupal\Core\State\StateInterface;
 use Symfony\Component\EventDispatcher\Event;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\KernelEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Defines a class which preloads non-admin routes.
@@ -21,7 +19,7 @@
  * list of all routes which most likely appear on the actual site, which are all
  * HTML routes not starting with "/admin".
  */
-class RoutePreloader implements EventSubscriberInterface {
+class RoutePreloader {
 
   /**
    * The route provider.
@@ -116,17 +114,4 @@ public function onFinishedRoutes(Event $event) {
     $this->nonAdminRoutesOnRebuild = array();
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    // Set a really low priority to catch as many as possible routes.
-    $events[RoutingEvents::ALTER] = array('onAlterRoutes', -1024);
-    $events[RoutingEvents::FINISHED] = array('onFinishedRoutes');
-    // Load the routes before the controller is executed (which happens after
-    // the kernel request event).
-    $events[KernelEvents::REQUEST][] = array('onRequest');
-    return $events;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
index 0fca7f8..75c4f9f 100644
--- a/core/lib/Drupal/Core/Routing/RouteProvider.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -7,20 +7,17 @@
 
 namespace Drupal\Core\Routing;
 
-use Drupal\Component\Utility\String;
 use Drupal\Core\State\StateInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Exception\RouteNotFoundException;
 use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
 use \Drupal\Core\Database\Connection;
 
 /**
  * A Route Provider front-end for all Drupal-stored routes.
  */
-class RouteProvider implements RouteProviderInterface, EventSubscriberInterface {
+class RouteProvider implements RouteProviderInterface {
 
   /**
    * The database connection from which to read route information.
@@ -320,12 +317,4 @@ public function reset() {
     $this->routes  = array();
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[RoutingEvents::FINISHED][] = array('reset');
-    return $events;
-  }
-
 }
diff --git a/core/modules/ban/ban.events.yml b/core/modules/ban/ban.events.yml
new file mode 100644
index 0000000..16d75ab
--- /dev/null
+++ b/core/modules/ban/ban.events.yml
@@ -0,0 +1,4 @@
+subscribers:
+  kernel.request:
+    - callback: ban.subscriber:onKernelRequestBannedIpCheck
+      priority: 40
diff --git a/core/modules/ban/ban.services.yml b/core/modules/ban/ban.services.yml
index 7f55ae6..42dab8a 100644
--- a/core/modules/ban/ban.services.yml
+++ b/core/modules/ban/ban.services.yml
@@ -4,6 +4,4 @@ services:
     arguments: ['@database']
   ban.subscriber:
     class: Drupal\ban\EventSubscriber\BanSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@ban.ip_manager']
diff --git a/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php b/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php
index d791ec3..aa1ed50 100644
--- a/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php
+++ b/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php
@@ -8,9 +8,7 @@
 namespace Drupal\ban\EventSubscriber;
 
 use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 use Drupal\ban\BanIpManagerInterface;
 use Drupal\Component\Utility\String;
@@ -18,7 +16,7 @@
 /**
  * Ban subscriber for controller requests.
  */
-class BanSubscriber implements EventSubscriberInterface {
+class BanSubscriber {
 
   /**
    * The manager used to check the IP against.
@@ -51,15 +49,4 @@ public function onKernelRequestBannedIpCheck(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestBannedIpCheck', 40);
-    return $events;
-  }
-
 }
diff --git a/core/modules/config/tests/config_events_test/config_events_test.events.yml b/core/modules/config/tests/config_events_test/config_events_test.events.yml
new file mode 100644
index 0000000..c6bb287
--- /dev/null
+++ b/core/modules/config/tests/config_events_test/config_events_test.events.yml
@@ -0,0 +1,7 @@
+subscribers:
+  config.save:
+    - config_events_test.event_subscriber:configEventRecorder
+  config.delete:
+    - config_events_test.event_subscriber:configEventRecorder
+  config.rename:
+    - config_events_test.event_subscriber:configEventRecorder
diff --git a/core/modules/config/tests/config_events_test/config_events_test.services.yml b/core/modules/config/tests/config_events_test/config_events_test.services.yml
index 12d6fb1..f9fe5a1 100644
--- a/core/modules/config/tests/config_events_test/config_events_test.services.yml
+++ b/core/modules/config/tests/config_events_test/config_events_test.services.yml
@@ -2,5 +2,3 @@ services:
   config_events_test.event_subscriber:
     class: Drupal\config_events_test\EventSubscriber
     arguments: ['@state']
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/config/tests/config_events_test/lib/Drupal/config_events_test/EventSubscriber.php b/core/modules/config/tests/config_events_test/lib/Drupal/config_events_test/EventSubscriber.php
index b127555..3f23ef1 100644
--- a/core/modules/config/tests/config_events_test/lib/Drupal/config_events_test/EventSubscriber.php
+++ b/core/modules/config/tests/config_events_test/lib/Drupal/config_events_test/EventSubscriber.php
@@ -13,7 +13,7 @@
 use Drupal\Core\State\StateInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
-class EventSubscriber implements EventSubscriberInterface {
+class EventSubscriber {
 
   /**
    * The state key value store.
@@ -48,13 +48,4 @@ public function configEventRecorder(ConfigCrudEvent $event) {
     ));
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[ConfigEvents::SAVE][] = array('configEventRecorder');
-    $events[ConfigEvents::DELETE][] = array('configEventRecorder');
-    $events[ConfigEvents::RENAME][] = array('configEventRecorder');
-    return $events;
-  }
 }
diff --git a/core/modules/config/tests/config_import_test/config_import_test.events.yml b/core/modules/config/tests/config_import_test/config_import_test.events.yml
new file mode 100644
index 0000000..80bb2a2
--- /dev/null
+++ b/core/modules/config/tests/config_import_test/config_import_test.events.yml
@@ -0,0 +1,7 @@
+subscribers:
+  config.save:
+    - callback: config_import_test.event_subscriber:onConfigSave
+      priority: 40
+  config.delete:
+    - callback: config_import_test.event_subscriber:onConfigDelete
+      priority: 40
diff --git a/core/modules/config/tests/config_import_test/config_import_test.services.yml b/core/modules/config/tests/config_import_test/config_import_test.services.yml
index da4fa1e..3455085 100644
--- a/core/modules/config/tests/config_import_test/config_import_test.services.yml
+++ b/core/modules/config/tests/config_import_test/config_import_test.services.yml
@@ -1,6 +1,4 @@
 services:
   config_import_test.event_subscriber:
     class: Drupal\config_import_test\EventSubscriber
-    tags:
-      - { name: event_subscriber }
     arguments: ['@state']
diff --git a/core/modules/config_translation/config_translation.events.yml b/core/modules/config_translation/config_translation.events.yml
new file mode 100644
index 0000000..f077771
--- /dev/null
+++ b/core/modules/config_translation/config_translation.events.yml
@@ -0,0 +1,3 @@
+subscribers:
+  routing.route_alter:
+    - config_translation.route_subscriber:onAlterRoutes
diff --git a/core/modules/config_translation/config_translation.services.yml b/core/modules/config_translation/config_translation.services.yml
index f4ed510..5a1e537 100644
--- a/core/modules/config_translation/config_translation.services.yml
+++ b/core/modules/config_translation/config_translation.services.yml
@@ -2,8 +2,6 @@ services:
   config_translation.route_subscriber:
     class: Drupal\config_translation\Routing\RouteSubscriber
     arguments: ['@plugin.manager.config_translation.mapper']
-    tags:
-      - { name: event_subscriber }
 
   config_translation.access.overview:
     class: Drupal\config_translation\Access\ConfigTranslationOverviewAccess
diff --git a/core/modules/content_translation/content_translation.events.yml b/core/modules/content_translation/content_translation.events.yml
new file mode 100644
index 0000000..e25e5ff
--- /dev/null
+++ b/core/modules/content_translation/content_translation.events.yml
@@ -0,0 +1,3 @@
+subscribers:
+  routing.route_alter:
+    - content_translation.subscriber:onAlterRoutes
diff --git a/core/modules/content_translation/content_translation.services.yml b/core/modules/content_translation/content_translation.services.yml
index da2acb2..0abfd8f 100644
--- a/core/modules/content_translation/content_translation.services.yml
+++ b/core/modules/content_translation/content_translation.services.yml
@@ -6,8 +6,6 @@ services:
   content_translation.subscriber:
     class: Drupal\content_translation\Routing\ContentTranslationRouteSubscriber
     arguments: ['@content_translation.manager']
-    tags:
-      - { name: event_subscriber }
 
   content_translation.overview_access:
     class: Drupal\content_translation\Access\ContentTranslationOverviewAccess
diff --git a/core/modules/field_ui/field_ui.events.yml b/core/modules/field_ui/field_ui.events.yml
new file mode 100644
index 0000000..d652919
--- /dev/null
+++ b/core/modules/field_ui/field_ui.events.yml
@@ -0,0 +1,4 @@
+subscribers:
+  routing.route_alter:
+    - callback: field_ui.subscriber:onAlterRoutes
+      priority: -100
diff --git a/core/modules/field_ui/field_ui.services.yml b/core/modules/field_ui/field_ui.services.yml
index 4f5ef7a..4d18967 100644
--- a/core/modules/field_ui/field_ui.services.yml
+++ b/core/modules/field_ui/field_ui.services.yml
@@ -2,8 +2,6 @@ services:
   field_ui.subscriber:
     class: Drupal\field_ui\Routing\RouteSubscriber
     arguments: ['@entity.manager']
-    tags:
-     - { name: event_subscriber }
   access_check.field_ui.view_mode:
     class: Drupal\field_ui\Access\ViewModeAccessCheck
     arguments: ['@entity.manager']
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php
index c8de23f..4cf8c1f 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php
@@ -130,13 +130,4 @@ protected function alterRoutes(RouteCollection $collection) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events = parent::getSubscribedEvents();
-    $events[RoutingEvents::ALTER] = array('onAlterRoutes', -100);
-    return $events;
-  }
-
 }
diff --git a/core/modules/hal/hal.events.yml b/core/modules/hal/hal.events.yml
new file mode 100644
index 0000000..8e820f1
--- /dev/null
+++ b/core/modules/hal/hal.events.yml
@@ -0,0 +1,4 @@
+subscribers:
+  kernel.request:
+    - callback: Drupal\hal\HalSubscriber::onKernelRequest
+      priority: 40
diff --git a/core/modules/hal/hal.services.yml b/core/modules/hal/hal.services.yml
index 4e89841..7e40df0 100644
--- a/core/modules/hal/hal.services.yml
+++ b/core/modules/hal/hal.services.yml
@@ -26,7 +26,3 @@ services:
     class: Drupal\hal\Encoder\JsonEncoder
     tags:
       - { name: encoder, priority: 10, format: hal_json }
-  hal.subscriber:
-    class: Drupal\hal\HalSubscriber
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/hal/lib/Drupal/hal/HalSubscriber.php b/core/modules/hal/lib/Drupal/hal/HalSubscriber.php
index 93a70bb..40f8760 100644
--- a/core/modules/hal/lib/Drupal/hal/HalSubscriber.php
+++ b/core/modules/hal/lib/Drupal/hal/HalSubscriber.php
@@ -7,14 +7,12 @@
 
 namespace Drupal\hal;
 
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Subscribes to the kernel request event to add HAL media types.
  */
-class HalSubscriber implements EventSubscriberInterface {
+class HalSubscriber {
 
   /**
    * Registers HAL formats with the Request class.
@@ -27,15 +25,4 @@ public function onKernelRequest(GetResponseEvent $event) {
     $request->setFormat('hal_json', 'application/hal+json');
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequest', 40);
-    return $events;
-  }
-
 }
diff --git a/core/modules/language/language.events.yml b/core/modules/language/language.events.yml
new file mode 100644
index 0000000..9bd2dc5
--- /dev/null
+++ b/core/modules/language/language.events.yml
@@ -0,0 +1,6 @@
+subscribers:
+  kernel.request:
+    - callback: ?language_request_subscriber:onKernelRequestLanguage
+      priority: 255
+  config.save:
+    - Drupal\language\EventSubscriber\ConfigSubscriber::onConfigSave
diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml
index 7396d57..b5ad47a 100644
--- a/core/modules/language/language.services.yml
+++ b/core/modules/language/language.services.yml
@@ -9,8 +9,6 @@ services:
       - [initLanguageManager]
   language.config_subscriber:
     class: Drupal\language\EventSubscriber\ConfigSubscriber
-    tags:
-      - { name: event_subscriber }
   language.config_factory_override:
     class: Drupal\language\Config\LanguageConfigFactoryOverride
     arguments: ['@config.storage', '@event_dispatcher', '@config.typed']
diff --git a/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php b/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php
index 1373a25..94aff12 100644
--- a/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php
+++ b/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php
@@ -15,7 +15,7 @@
 /**
  * Deletes the container if default language has changed.
  */
-class ConfigSubscriber implements EventSubscriberInterface {
+class ConfigSubscriber {
 
   /**
    * Causes the container to be rebuilt on the next request.
@@ -32,12 +32,4 @@ public function onConfigSave(ConfigCrudEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[ConfigEvents::SAVE][] = array('onConfigSave', 0);
-    return $events;
-  }
-
 }
diff --git a/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php b/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php
index 95eb700..3493d55 100644
--- a/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php
+++ b/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php
@@ -27,7 +27,6 @@ public function register(ContainerBuilder $container) {
     // The following services are needed only on multilingual sites.
     if ($this->isMultilingual()) {
       $container->register('language_request_subscriber', 'Drupal\language\EventSubscriber\LanguageRequestSubscriber')
-        ->addTag('event_subscriber')
         ->addArgument(new Reference('language_manager'))
         ->addArgument(new Reference('language_negotiator'))
         ->addArgument(new Reference('string_translation'))
diff --git a/core/modules/node/node.events.yml b/core/modules/node/node.events.yml
new file mode 100644
index 0000000..be767c4
--- /dev/null
+++ b/core/modules/node/node.events.yml
@@ -0,0 +1,3 @@
+subscribers:
+  routing.route_alter:
+    - node.admin_path.route_subscriber:onAlterRoutes
diff --git a/core/modules/node/node.services.yml b/core/modules/node/node.services.yml
index e211f7b..5e149e0 100644
--- a/core/modules/node/node.services.yml
+++ b/core/modules/node/node.services.yml
@@ -15,5 +15,3 @@ services:
   node.admin_path.route_subscriber:
     class: Drupal\node\EventSubscriber\NodeAdminRouteSubscriber
     arguments: ['@config.factory']
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/system/lib/Drupal/system/EventSubscriber/AutomaticCron.php b/core/modules/system/lib/Drupal/system/EventSubscriber/AutomaticCron.php
index 15c5b6c..7e43c30 100644
--- a/core/modules/system/lib/Drupal/system/EventSubscriber/AutomaticCron.php
+++ b/core/modules/system/lib/Drupal/system/EventSubscriber/AutomaticCron.php
@@ -17,7 +17,7 @@
 /**
  * A subscriber running cron when a request terminates.
  */
-class AutomaticCron implements EventSubscriberInterface {
+class AutomaticCron {
 
   /**
    * The cron service.
@@ -77,16 +77,4 @@ public function onTerminate(PostResponseEvent $event) {
     }
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
-
-    return $events;
-  }
-
 }
diff --git a/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php b/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php
index 765b824..1d43c81 100644
--- a/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php
+++ b/core/modules/system/lib/Drupal/system/SystemConfigSubscriber.php
@@ -9,19 +9,18 @@
 
 use Drupal\Core\Config\ConfigImporterEvent;
 use Drupal\Core\Config\ConfigImportValidateEventSubscriberBase;
-use Drupal\Core\Config\StorageDispatcher;
 
 /**
- * System Config subscriber.
+ * Checks that the configuration synchronization is valid.
+ *
+ * This event listener implements two checks:
+ *   - prevents deleting all configuration.
+ *   - checks that the system.site:uuid's in the source and target match.
  */
 class SystemConfigSubscriber extends ConfigImportValidateEventSubscriberBase {
 
   /**
-   * Checks that the configuration synchronization is valid.
-   *
-   * This event listener implements two checks:
-   *   - prevents deleting all configuration.
-   *   - checks that the system.site:uuid's in the source and target match.
+   * Checks that the import source storage is not empty.
    *
    * @param ConfigImporterEvent $event
    *   The config import event.
@@ -35,4 +34,5 @@ public function onConfigImporterValidate(ConfigImporterEvent $event) {
       $event->getConfigImporter()->logError($this->t('Site UUID in source storage does not match the target storage.'));
     }
   }
+
 }
diff --git a/core/modules/system/system.events.yml b/core/modules/system/system.events.yml
new file mode 100644
index 0000000..b64010d
--- /dev/null
+++ b/core/modules/system/system.events.yml
@@ -0,0 +1,10 @@
+subscribers:
+  routing.route_alter:
+    - callback: system.admin_path.route_subscriber:onAlterRoutes
+      priority: -200
+  config.importer.validate:
+    - callback: Drupal\system\SystemConfigSubscriber::onConfigImporterValidate
+      priority: 20
+  kernel.terminate:
+    - callback: system.automatic_cron:onTerminate
+      priority: 100
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 8d09004..64b782e 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -17,8 +17,6 @@ services:
       - { name: path_processor_inbound, priority: 200 }
   system.admin_path.route_subscriber:
     class: Drupal\system\EventSubscriber\AdminRouteSubscriber
-    tags:
-      - { name: event_subscriber }
   theme.negotiator.system.batch:
     class: Drupal\system\Theme\BatchNegotiator
     arguments: ['@batch.storage']
@@ -26,10 +24,6 @@ services:
       - { name: theme_negotiator, priority: 1000 }
   system.config_subscriber:
     class: Drupal\system\SystemConfigSubscriber
-    tags:
-      - { name: event_subscriber }
   system.automatic_cron:
     class: Drupal\system\EventSubscriber\AutomaticCron
     arguments: ['@cron', '@config.factory', '@state']
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/system/tests/modules/form_test/form_test.events.yml b/core/modules/system/tests/modules/form_test/form_test.events.yml
new file mode 100644
index 0000000..56967e1
--- /dev/null
+++ b/core/modules/system/tests/modules/form_test/form_test.events.yml
@@ -0,0 +1,3 @@
+subscribers:
+  kernel.request:
+    - Drupal\form_test\EventSubscriber\FormTestEventSubscriber::onKernelRequest
diff --git a/core/modules/system/tests/modules/form_test/form_test.services.yml b/core/modules/system/tests/modules/form_test/form_test.services.yml
index 0201650..42ae7a6 100644
--- a/core/modules/system/tests/modules/form_test/form_test.services.yml
+++ b/core/modules/system/tests/modules/form_test/form_test.services.yml
@@ -1,7 +1,3 @@
 services:
   form_test.form.serviceform:
     class: Drupal\form_test\FormTestServiceObject
-  form_test.event_subscriber:
-    class: Drupal\form_test\EventSubscriber\FormTestEventSubscriber
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/EventSubscriber/FormTestEventSubscriber.php b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/EventSubscriber/FormTestEventSubscriber.php
index d560f18..d6319ce 100644
--- a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/EventSubscriber/FormTestEventSubscriber.php
+++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/EventSubscriber/FormTestEventSubscriber.php
@@ -7,14 +7,12 @@
 
 namespace Drupal\form_test\EventSubscriber;
 
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Test event subscriber to add new attributes to the request.
  */
-class FormTestEventSubscriber implements EventSubscriberInterface {
+class FormTestEventSubscriber {
 
   /**
    * Adds custom attributes to the request object.
@@ -28,12 +26,4 @@ public function onKernelRequest(GetResponseEvent $event) {
     $request->attributes->set('request_attribute', 'request_value');
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequest');
-    return $events;
-  }
-
 }
diff --git a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php
index 2071a37..9475b58 100644
--- a/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/modules/system/tests/modules/menu_test/lib/Drupal/menu_test/EventSubscriber/MaintenanceModeSubscriber.php
@@ -7,14 +7,12 @@
 
 namespace Drupal\menu_test\EventSubscriber;
 
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Maintenance mode subscriber to set site online on a test.
  */
-class MaintenanceModeSubscriber implements EventSubscriberInterface {
+class MaintenanceModeSubscriber {
 
   /**
    * Set the page online if called from a certain path.
@@ -30,12 +28,4 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestMaintenance', 35);
-    return $events;
-  }
-
 }
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.events.yml b/core/modules/system/tests/modules/menu_test/menu_test.events.yml
new file mode 100644
index 0000000..234b523
--- /dev/null
+++ b/core/modules/system/tests/modules/menu_test/menu_test.events.yml
@@ -0,0 +1,4 @@
+subscribers:
+  kernel.request:
+    - callback: Drupal\menu_test\EventSubscriber\MaintenanceModeSubscriber::onKernelRequestMaintenance
+      priority: 35
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.services.yml b/core/modules/system/tests/modules/menu_test/menu_test.services.yml
index b52f8cf..8841320 100644
--- a/core/modules/system/tests/modules/menu_test/menu_test.services.yml
+++ b/core/modules/system/tests/modules/menu_test/menu_test.services.yml
@@ -1,9 +1,4 @@
 services:
-  menu_test_maintenance_mode_subscriber:
-    class: Drupal\menu_test\EventSubscriber\MaintenanceModeSubscriber
-    tags:
-      - { name: event_subscriber }
-
   theme.negotiator.test_theme:
     class: Drupal\menu_test\Theme\TestThemeNegotiator
     tags:
diff --git a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php b/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php
index aa0a5f2..05c5032 100644
--- a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php
+++ b/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php
@@ -9,11 +9,9 @@
 
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\DestructableInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
-class TestClass implements EventSubscriberInterface, DestructableInterface {
+class TestClass implements DestructableInterface {
 
   /**
    * The state keyvalue collection.
@@ -40,17 +38,6 @@ public function onKernelRequestTest(GetResponseEvent $event) {
   }
 
   /**
-   * Registers methods as kernel listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestTest', 100);
-    return $events;
-  }
-
-  /**
    * Implements \Drupal\Core\DestructableInterface::destruct().
    */
   public function destruct() {
diff --git a/core/modules/system/tests/modules/service_provider_test/service_provider_test.events.yml b/core/modules/system/tests/modules/service_provider_test/service_provider_test.events.yml
new file mode 100644
index 0000000..22d02c3
--- /dev/null
+++ b/core/modules/system/tests/modules/service_provider_test/service_provider_test.events.yml
@@ -0,0 +1,4 @@
+subscribers:
+  kernel.request:
+    - callback: service_provider_test_class:onKernelRequestTest
+      priority: 100
diff --git a/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml b/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml
index dda70f5..eb1cc9b 100644
--- a/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml
+++ b/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml
@@ -2,6 +2,5 @@ services:
   service_provider_test_class:
     class: Drupal\service_provider_test\TestClass
     tags:
-      - { name: event_subscriber }
       - { name: needs_destruction }
     arguments: ['@state']
diff --git a/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php b/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php
index 55225ae..330e198 100644
--- a/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php
+++ b/core/modules/system/tests/modules/session_test/lib/Drupal/session_test/EventSubscriber/SessionTestSubscriber.php
@@ -7,16 +7,14 @@
 
 namespace Drupal\session_test\EventSubscriber;
 
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
-use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 
 /**
  * Defines a test session subscriber that checks whether the session is empty.
  */
-class SessionTestSubscriber implements EventSubscriberInterface {
+class SessionTestSubscriber {
 
   /*
    * Stores whether $_SESSION is empty at the beginning of the request.
@@ -62,16 +60,4 @@ public function onKernelResponseSessionTest(FilterResponseEvent $event) {
     $response->headers->set('X-Session-Empty', $this->emptySession);
   }
 
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::RESPONSE][] = array('onKernelResponseSessionTest', 300);
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestSessionTest', 100);
-    return $events;
-  }
-
 }
diff --git a/core/modules/system/tests/modules/session_test/session_test.events.yml b/core/modules/system/tests/modules/session_test/session_test.events.yml
new file mode 100644
index 0000000..27f061b
--- /dev/null
+++ b/core/modules/system/tests/modules/session_test/session_test.events.yml
@@ -0,0 +1,7 @@
+subscribers:
+  kernel.request:
+    - callback: Drupal\session_test\EventSubscriber\SessionTestSubscriber::onKernelRequestSessionTest
+      priority: 300
+  kernel.response:
+    - callback: Drupal\session_test\EventSubscriber\SessionTestSubscriber::onKernelResponseSessionTest
+      priority: 100
diff --git a/core/modules/system/tests/modules/session_test/session_test.services.yml b/core/modules/system/tests/modules/session_test/session_test.services.yml
deleted file mode 100644
index 8ef2e20..0000000
--- a/core/modules/system/tests/modules/session_test/session_test.services.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-services:
-  session_test.subscriber:
-    class: Drupal\session_test\EventSubscriber\SessionTestSubscriber
-    tags:
-      - { name: event_subscriber }
diff --git a/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php b/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
index 0cdf668..b86ede2 100644
--- a/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
+++ b/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
@@ -7,14 +7,13 @@
 
 namespace Drupal\theme_test\EventSubscriber;
 
-use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\DependencyInjection\ContainerAware;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
  * Theme test subscriber for controller requests.
  */
-class ThemeTestSubscriber implements EventSubscriberInterface {
+class ThemeTestSubscriber extends ContainerAware {
 
   /**
    * The used container.
@@ -23,7 +22,6 @@ class ThemeTestSubscriber implements EventSubscriberInterface {
    */
   protected $container;
 
-
   /**
    * Generates themed output early in a page request.
    *
@@ -64,13 +62,4 @@ public function onView(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onRequest');
-    $events[KernelEvents::VIEW][] = array('onView', -1000);
-    return $events;
-  }
-
 }
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.events.yml b/core/modules/system/tests/modules/theme_test/theme_test.events.yml
new file mode 100644
index 0000000..c00f5a9
--- /dev/null
+++ b/core/modules/system/tests/modules/theme_test/theme_test.events.yml
@@ -0,0 +1,6 @@
+subscribers:
+  kernel.request:
+    - Drupal\theme_test\EventSubscriber\ThemeTestSubscriber::onRequest
+  kernel.view:
+    - callback: Drupal\theme_test\EventSubscriber\ThemeTestSubscriber::onView
+      priority: -1000
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.services.yml b/core/modules/system/tests/modules/theme_test/theme_test.services.yml
index 69fd3ca..41d944b 100644
--- a/core/modules/system/tests/modules/theme_test/theme_test.services.yml
+++ b/core/modules/system/tests/modules/theme_test/theme_test.services.yml
@@ -1,9 +1,4 @@
 services:
-  theme_test.subscriber:
-    class: Drupal\theme_test\EventSubscriber\ThemeTestSubscriber
-    tags:
-      - { name: event_subscriber }
-
   theme.negotiator.test_custom_theme:
     class: Drupal\theme_test\Theme\CustomThemeNegotiator
     tags:
diff --git a/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php b/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php
index 3c478f7..2e5d4aa 100644
--- a/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php
+++ b/core/modules/user/lib/Drupal/user/EventSubscriber/MaintenanceModeSubscriber.php
@@ -7,15 +7,13 @@
 
 namespace Drupal\user\EventSubscriber;
 
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
 
 /**
  * Maintenance mode subscriber to logout users.
  */
-class MaintenanceModeSubscriber implements EventSubscriberInterface {
+class MaintenanceModeSubscriber {
 
   /**
    * Determine whether the page is configured to be offline.
@@ -71,12 +69,4 @@ public function onKernelRequestMaintenance(GetResponseEvent $event) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestMaintenance', 35);
-    return $events;
-  }
-
 }
diff --git a/core/modules/user/user.events.yml b/core/modules/user/user.events.yml
new file mode 100644
index 0000000..4862e71
--- /dev/null
+++ b/core/modules/user/user.events.yml
@@ -0,0 +1,4 @@
+subscribers:
+  kernel.request:
+    - callback: Drupal\user\EventSubscriber\MaintenanceModeSubscriber::onKernelRequestMaintenance
+      priority: 35
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index 03bb4c2..9fb677b 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -31,10 +31,6 @@ services:
   user.autocomplete:
     class: Drupal\user\UserAutocomplete
     arguments: ['@database', '@config.factory', '@entity.manager', '@entity.query']
-  user_maintenance_mode_subscriber:
-    class: Drupal\user\EventSubscriber\MaintenanceModeSubscriber
-    tags:
-      - { name: event_subscriber }
   theme.negotiator.admin_theme:
     class: Drupal\user\Theme\AdminNegotiator
     arguments: ['@current_user', '@config.factory', '@entity.manager', '@router.admin_context']
diff --git a/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php b/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php
index 9fec99b..162cf76 100644
--- a/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php
+++ b/core/modules/views/lib/Drupal/views/EventSubscriber/RouteSubscriber.php
@@ -81,16 +81,6 @@ public function reset() {
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events = parent::getSubscribedEvents();
-    $events[KernelEvents::VIEW][] = array('onHtmlPage', 75);
-    $events[RoutingEvents::FINISHED] = array('routeRebuildFinished');
-    return $events;
-  }
-
-  /**
    * Gets all the views and display IDs using a route.
    */
   protected function getViewsDisplayIDsWithRoute() {
diff --git a/core/modules/views/views.events.yml b/core/modules/views/views.events.yml
new file mode 100644
index 0000000..7c88e35
--- /dev/null
+++ b/core/modules/views/views.events.yml
@@ -0,0 +1,8 @@
+subscribers:
+  kernel.view:
+    - callback: views.route_subscriber:onHtmlPage
+      priority: 75
+  routing.route_alter:
+    - views.route_subscriber:onAlterRoutes
+  routing.route_finished:
+    - views.route_subscriber:routeRebuildFinished
diff --git a/core/modules/views/views.services.yml b/core/modules/views/views.services.yml
index 61b6e70..f174ddf 100644
--- a/core/modules/views/views.services.yml
+++ b/core/modules/views/views.services.yml
@@ -71,8 +71,6 @@ services:
   views.route_subscriber:
     class: Drupal\views\EventSubscriber\RouteSubscriber
     arguments: ['@entity.manager', '@state']
-    tags:
-      - { name: 'event_subscriber' }
   views.route_access_check:
     class: Drupal\views\ViewsAccessCheck
     tags:
diff --git a/core/tests/Drupal/Tests/Core/EventListenerPassTest.php b/core/tests/Drupal/Tests/Core/EventListenerPassTest.php
new file mode 100644
index 0000000..f3a43ee
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/EventListenerPassTest.php
@@ -0,0 +1,394 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\EventListenerPassTest.
+ */
+
+namespace Drupal\Tests\Core;
+
+use Drupal\Component\Discovery\DiscoverableInterface;
+use Drupal\Core\EventListenerPass;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Tests the event listener pass.
+ *
+ * @group Drupal
+ *
+ * @coversDefaultClass \Drupal\EventListenerPassTest
+ */
+class EventListenerPassTest extends UnitTestCase {
+
+  /**
+   * The tested event listener pass.
+   *
+   * @var \Drupal\Core\EventListenerPass|\Drupal\Tests\Core\TestEventListenerPass
+   */
+  protected $eventListenerPass;
+
+  /**
+   * The mocked event dispatcher.
+   *
+   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $eventDispatcher;
+
+  /**
+   * The mocked module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $moduleHandler;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Event listener pass',
+      'description' => 'Tests the event listener pass',
+      'group' => 'Bootstrap',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->eventListenerPass = new TestEventListenerPass();
+  }
+
+  /**
+   * Creates a container with a event_dispatcher and module handler service.
+   *
+   * @return \Symfony\Component\DependencyInjection\ContainerBuilder
+   *   The created container.
+   */
+  protected function setUpContainer() {
+    $container = new ContainerBuilder();
+    $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
+    $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
+    $container->set('event_dispatcher', $this->eventDispatcher);
+    $container->register('event_dispatcher', 'Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher')
+      ->setArguments(array(new Reference('service_container')));
+
+    $container->set('module_handler', $this->moduleHandler);
+    return $container;
+  }
+
+  /**
+   * Tests the event listener pass without any event.
+   */
+  public function testNoEvent() {
+    $container = $this->setUpContainer();
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array()));
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+
+    $this->eventListenerPass->process($container);
+
+    $this->assertEquals(3, count($container->getServiceIds()));
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one class based event.
+   */
+  public function testEvent() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = 'Drupal\Tests\Core\TestClass::subscriberMethod';
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $expected_calls[] = array('addListenerService', array('example', array('event_listener.Drupal.Tests.Core.TestClass', 'subscriberMethod')));
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one class based event with a priority.
+   */
+  public function testEventWithPriority() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = array(
+      'callback' => 'Drupal\Tests\Core\TestClass::subscriberMethod',
+      'priority' => 10,
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $expected_calls[] = array('addListenerService', array('example', array('event_listener.Drupal.Tests.Core.TestClass', 'subscriberMethod'), 10));
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one service based event.
+   */
+  public function testServiceEventWithoutPriority() {
+    $container = $this->setUpContainer();
+    $container->register('subscriber_service', 'Drupal\Tests\Core\TestClass');
+
+    $info['subscribers']['example'][] = array(
+      'callback' => 'subscriber_service:subscriberMethod',
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $expected_calls[] = array('addListenerService', array('example', array('subscriber_service', 'subscriberMethod')));
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one service based event with a priority.
+   */
+  public function testServiceEventWithPriority() {
+    $container = $this->setUpContainer();
+    $container->register('subscriber_service', 'Drupal\Tests\Core\TestClass');
+
+    $info['subscribers']['example'][] = array(
+      'callback' => 'subscriber_service:subscriberMethod',
+      'priority' => 10,
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $expected_calls[] = array('addListenerService', array('example', array('subscriber_service', 'subscriberMethod'), 10));
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one service which does not exist.
+   *
+   * @expectedException \InvalidArgumentException
+   * @expectedExceptionMessage Service "subscriber_service" does not exist.
+   *
+   */
+  public function testNotExistingService() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = array(
+      'callback' => 'subscriber_service:subscriberMethod',
+      'priority' => 10,
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+  }
+
+  /**
+   * Tests the event listener pass with one optional non existing service.
+   */
+  public function testOptionalNonExistingService() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = array(
+      'callback' => '?subscriber_service:subscriberMethod',
+      'priority' => 10,
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one optional non existent class.
+   */
+  public function testOptionalNotExistingClass() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = array(
+      'callback' => '?Drupal\Tests\Core\TestClass2::subscriberMethod',
+      'priority' => 10,
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with one class which does not exist.
+   *
+   * @expectedException \InvalidArgumentException
+   * @expectedExceptionMessage Class "Drupal\Tests\Core\TestClass2" does not exist.
+   *
+   */
+  public function testNotExistingClass() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = array(
+      'callback' => 'Drupal\Tests\Core\TestClass2::subscriberMethod',
+      'priority' => 10,
+    );
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+  }
+
+
+  /**
+   * Tests the event listener pass with a bunch of services/classes.
+   */
+  public function testMultipleEvents() {
+    $container = $this->setUpContainer();
+    $container->register('subscriber_service', 'Drupal\Tests\Core\TestClass');
+
+    // Set a service without a priority.
+    $info['subscribers']['example'][] = array(
+      'callback' => 'subscriber_service:subscriberMethod',
+    );
+
+    // Setup the same method with different priorities.
+    $info['subscribers']['example2'][] = array(
+      'callback' => 'subscriber_service:subscriberMethod2',
+      'priority' => -10,
+    );
+
+    $info['subscribers']['example2'][] = array(
+      'callback' => 'subscriber_service:subscriberMethod2',
+      'priority' => 10,
+    );
+
+    // Subscribe to different events with the same method and same priority.
+    $info['subscribers']['example3'][] = array(
+      'callback' => 'Drupal\Tests\Core\TestClass::subscriberMethod2',
+      'priority' => 10,
+    );
+    $info['subscribers']['example4'][] = array(
+      'callback' => 'Drupal\Tests\Core\TestClass::subscriberMethod2',
+      'priority' => 10,
+    );
+
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+
+    $definition = $container->getDefinition('event_dispatcher');
+    $expected_calls = array();
+    $expected_calls[] = array('addListenerService', array('example', array('subscriber_service', 'subscriberMethod')));
+    $expected_calls[] = array('addListenerService', array('example2', array('subscriber_service', 'subscriberMethod2'), -10));
+    $expected_calls[] = array('addListenerService', array('example2', array('subscriber_service', 'subscriberMethod2'), 10));
+    $expected_calls[] = array('addListenerService', array('example3', array('event_listener.Drupal.Tests.Core.TestClass', 'subscriberMethod2'), 10));
+    $expected_calls[] = array('addListenerService', array('example4', array('event_listener.Drupal.Tests.Core.TestClass', 'subscriberMethod2'), 10));
+    $this->assertEquals($expected_calls, $definition->getMethodCalls());
+  }
+
+  /**
+   * Tests the event listener pass with an invalid yaml file.
+   *
+   * @expectedException \UnexpectedValueException
+   * @expectedExceptionMessage Unable to parse the callback name "test_service-test"
+   */
+  public function testInvalidYaml() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers']['example'][] = 'test_service-test';
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+  }
+
+  /**
+   * Tests the evnet listener pass with an yaml file without any subscribers.
+   */
+  public function testEmptyYaml() {
+    $container = $this->setUpContainer();
+
+    $info['subscribers'] = NULL;
+    $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface');
+    $yaml_discovery->expects($this->once())
+      ->method('findAll')
+      ->will($this->returnValue(array($info)));
+
+    $this->eventListenerPass->setYamlDiscovery($yaml_discovery);
+    $this->eventListenerPass->process($container);
+    $definition = $container->getDefinition('event_dispatcher');
+    $this->assertEquals(array(), $definition->getMethodCalls());
+  }
+
+}
+
+class TestEventListenerPass extends EventListenerPass {
+
+  public function setYamlDiscovery(DiscoverableInterface $yaml_discovery) {
+    $this->yamlDiscovery = $yaml_discovery;
+  }
+
+  protected function getYamlDiscovery(ModuleHandlerInterface $module_handler) {
+    return $this->yamlDiscovery;
+  }
+
+}
+
+class TestClass {
+  public function subscriberMethod() {}
+  public function subscriberMethod2() {}
+}
