diff --git a/core/core.services.yml b/core/core.services.yml
index d1223e9..aaed174 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -795,16 +795,6 @@ services:
     arguments: ['@router.route_provider', '@state', '@cache.bootstrap']
     tags:
       - { name: 'event_subscriber' }
-  router.matcher.final_matcher:
-    class: Drupal\Core\Routing\UrlMatcher
-    arguments: ['@path.current']
-  router.matcher:
-    class: Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher
-    arguments: ['@router.route_provider']
-    calls:
-      - [setFinalMatcher, ['@router.matcher.final_matcher']]
-    tags:
-      - { name: service_collector, tag: non_lazy_route_filter, call: addRouteFilter }
   route_filter.lazy_collector:
     class: Drupal\Core\Routing\LazyRouteFilter
     tags:
@@ -838,16 +828,13 @@ services:
   router:
     class: Drupal\Core\Routing\AccessAwareRouter
     arguments: ['@router.no_access_checks', '@access_manager', '@current_user']
-  router.dynamic:
-    class: Symfony\Cmf\Component\Routing\DynamicRouter
-    arguments: ['@router.request_context', '@router.matcher', '@url_generator']
+  router.no_access_checks:
+    class: \Drupal\Core\Routing\DynamicRouter
+    arguments: ['@router.route_provider', '@path.current']
     tags:
       - { name: service_collector, tag: non_lazy_route_enhancer, call: addRouteEnhancer }
-  router.no_access_checks:
-    class: Symfony\Cmf\Component\Routing\ChainRouter
     calls:
       - [setContext, ['@router.request_context']]
-      - [add, ['@router.dynamic']]
   router.path_roots_subscriber:
     class: Drupal\Core\EventSubscriber\PathRootsSubscriber
     arguments: ['@state']
diff --git a/core/lib/Drupal/Core/Routing/AccessAwareRouter.php b/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
index 9346b0a..2bcabfb 100644
--- a/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
+++ b/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
@@ -5,7 +5,6 @@
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Access\AccessResultReasonInterface;
 use Drupal\Core\Session\AccountInterface;
-use Symfony\Cmf\Component\Routing\ChainRouter;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\Routing\RequestContext as SymfonyRequestContext;
@@ -39,14 +38,14 @@ class AccessAwareRouter implements AccessAwareRouterInterface {
   /**
    * Constructs a router for Drupal with access check and upcasting.
    *
-   * @param \Symfony\Cmf\Component\Routing\ChainRouter $chain_router
+   * @param \Drupal\Core\Routing\DynamicRouter $chain_router
    *   The chain router doing the actual routing.
    * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
    *   The access manager.
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The account to use in access checks.
    */
-  public function __construct(ChainRouter $chain_router, AccessManagerInterface $access_manager, AccountInterface $account) {
+  public function __construct(DynamicRouter $chain_router, AccessManagerInterface $access_manager, AccountInterface $account) {
     $this->chainRouter = $chain_router;
     $this->accessManager = $access_manager;
     $this->account = $account;
diff --git a/core/lib/Drupal/Core/Routing/DynamicRouter.php b/core/lib/Drupal/Core/Routing/DynamicRouter.php
new file mode 100644
index 0000000..559b917
--- /dev/null
+++ b/core/lib/Drupal/Core/Routing/DynamicRouter.php
@@ -0,0 +1,211 @@
+<?php
+
+namespace Drupal\Core\Routing;
+
+use Drupal\Core\Path\CurrentPathStack;
+use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface as BaseRouteEnhancerInterface;
+use Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface as BaseRouteFilterInterface;
+use Symfony\Cmf\Component\Routing\RouteProviderInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Dynamic router handles the central piece of logic of routing in Drupal.
+ *
+ * It consists of several steps, of which each are explained in more details
+ * below:
+ *   - Get a collection of routes which potentially match the current request.
+ *     The storage and filtering of them are handled in the route provid
+ */
+class DynamicRouter extends UrlMatcher implements RequestMatcherInterface {
+
+  /**
+   * The route provider responsible for the first-pass match.
+   *
+   * @var \Symfony\Cmf\Component\Routing\RouteProviderInterface
+   */
+  protected $routeProvider;
+
+  /**
+   * @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[]
+   */
+  protected $enhancers = [];
+
+  /**
+   * Cached sorted list of enhancers
+   *
+   * @var \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[]
+   */
+  protected $sortedEnhancers;
+
+  /**
+   * An array of RouteFilterInterface objects.
+   *
+   * @var \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[]
+   */
+  protected $filters = [];
+
+  /**
+   * Array of RouteFilterInterface objects, sorted.
+   *
+   * @var \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[]
+   */
+  protected $sortedFilters;
+
+  /**
+   * @param \Symfony\Cmf\Component\Routing\RouteProviderInterface $route_provider
+   * @param \Drupal\Core\Path\CurrentPathStack $current_path
+   */
+  public function __construct(RouteProviderInterface $route_provider, CurrentPathStack $current_path) {
+    parent::__construct($current_path);
+    $this->routeProvider = $route_provider;
+  }
+
+  public function addRouteEnhancer(BaseRouteEnhancerInterface $routeEnhancer, $priority) {
+    $this->enhancers[$priority][] = $routeEnhancer;
+    return $this;
+  }
+
+  public function addRouteFilter(BaseRouteFilterInterface $routeFilter, $priority) {
+    $this->filters[$priority][] = $routeFilter;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function match($pathinfo) {
+    $request = Request::create($pathinfo);
+
+    return $this->matchRequest($request);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function matchRequest(Request $request) {
+    $collection = $this->routeProvider->getRouteCollectionForRequest($request);
+
+    $collection = $this->applyRouteFilters($collection, $request);
+
+    if ($ret = $this->matchCollection(rawurldecode($this->currentPath->getPath()), $collection)) {
+      return $this->applyRouteEnhancers($ret, $request);
+    }
+
+    throw 0 < count($this->allow)
+      ? new MethodNotAllowedException(array_unique($this->allow))
+      : new ResourceNotFoundException(sprintf('No routes found for "%s".', $this->currentPath->getPath()));
+  }
+
+  /**
+   * Apply the route enhancers to the defaults, according to priorities
+   *
+   * @param array $defaults
+   *   The defaults coming from the final matched route.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
+   *
+   * @return array
+   *   The request attributes after applying the enhancers.
+   */
+  protected function applyRouteEnhancers($defaults, Request $request) {
+    foreach ($this->getRouteEnhancers() as $enhancer) {
+      $defaults = $enhancer->enhance($defaults, $request);
+    }
+
+    return $defaults;
+  }
+
+  /**
+   * Sorts the enhancers and flattens them.
+   *
+   * @return \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[]
+   *   The enhancers ordered by priority.
+   */
+  public function getRouteEnhancers() {
+    if (!isset($this->sortedEnhancers)) {
+      $this->sortedEnhancers = $this->sortRouteEnhancers();
+    }
+
+    return $this->sortedEnhancers;
+  }
+
+  /**
+   * Sort enhancers by priority.
+   *
+   * The highest priority number is the highest priority (reverse sorting).
+   *
+   * @return \Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface[]
+   *   The sorted enhancers.
+   */
+  protected function sortRouteEnhancers() {
+    $sortedEnhancers = [];
+    krsort($this->enhancers);
+
+    foreach ($this->enhancers as $enhancers) {
+      $sortedEnhancers = array_merge($sortedEnhancers, $enhancers);
+    }
+
+    return $sortedEnhancers;
+  }
+
+  /**
+   * Applies all route filters to a given route collection.
+   *
+   * This method reduces the sets of routes further down, for example by
+   * checking the HTTP method.
+   *
+   * @param \Symfony\Component\Routing\RouteCollection $collection
+   *   The route collection.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request.
+   *
+   * @return \Symfony\Component\Routing\RouteCollection
+   *   The filtered/sorted route collection.
+   */
+  protected function applyRouteFilters(RouteCollection $collection, Request $request) {
+    // Route filters are expected to throw an exception themselves if they
+    // end up filtering the list down to 0.
+    foreach ($this->getRouteFilters() as $filter) {
+      $collection = $filter->filter($collection, $request);
+    }
+
+    return $collection;
+  }
+
+  /**
+   * Sorts the filters and flattens them.
+   *
+   * @return \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[]
+   *   The filters ordered by priority
+   */
+  public function getRouteFilters() {
+    if (!isset($this->sortedFilters)) {
+      $this->sortedFilters = $this->sortFilters();
+    }
+
+    return $this->sortedFilters;
+  }
+
+  /**
+   * Sort filters by priority.
+   *
+   * The highest priority number is the highest priority (reverse sorting).
+   *
+   * @return \Symfony\Cmf\Component\Routing\NestedMatcher\RouteFilterInterface[]
+   *   The sorted filters.
+   */
+  protected function sortFilters() {
+    $sortedFilters = [];
+    krsort($this->filters);
+
+    foreach ($this->filters as $filters) {
+      $sortedFilters = array_merge($sortedFilters, $filters);
+    }
+
+    return $sortedFilters;
+  }
+
+}
