diff --git a/core/lib/Drupal/Core/Menu/MenuLinkManager.php b/core/lib/Drupal/Core/Menu/MenuLinkManager.php
index 3647e07..18340ab 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkManager.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkManager.php
@@ -12,9 +12,11 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\ModuleDependencyTrait;
 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\Core\Plugin\Discovery\YamlDiscovery;
 use Drupal\Core\Plugin\Factory\ContainerFactory;
+use Symfony\Component\Routing\RouteCollection;
 
 
 /**
@@ -24,6 +26,8 @@
  */
 class MenuLinkManager implements MenuLinkManagerInterface {
 
+  use ModuleDependencyTrait;
+
   /**
    * Provides some default values for the definition of all menu link plugins.
    *
@@ -104,7 +108,6 @@ class MenuLinkManager implements MenuLinkManagerInterface {
    */
   protected $moduleHandler;
 
-
   /**
    * Constructs a \Drupal\Core\Menu\MenuLinkManager object.
    *
@@ -183,6 +186,10 @@ public function getDefinitions() {
         unset($definitions[$plugin_id]);
       }
     }
+
+    // Filter out definitions with unmet module dependencies.
+    $this->filterByModuleDependencies($definitions);
+
     return $definitions;
   }
 
diff --git a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
index 95928e4..1adff9d 100644
--- a/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
+++ b/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php
@@ -27,6 +27,7 @@
 class DefaultPluginManager extends PluginManagerBase implements PluginManagerInterface, CachedDiscoveryInterface {
 
   use DiscoveryCachedTrait;
+  use ModuleDependencyTrait;
 
   /**
    * Cache backend instance.
@@ -239,6 +240,9 @@ protected function findDefinitions() {
         unset($definitions[$plugin_id]);
       }
     }
+
+    $this->filterByModuleDependencies($definitions);
+
     return $definitions;
   }
 
diff --git a/core/lib/Drupal/Core/Plugin/ModuleDependencyTrait.php b/core/lib/Drupal/Core/Plugin/ModuleDependencyTrait.php
new file mode 100644
index 0000000..218a3f9
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/ModuleDependencyTrait.php
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Plugin\ModuleDependencyTrait.
+ */
+
+namespace Drupal\Core\Plugin;
+
+use Drupal\Component\Discovery\YamlDiscovery;
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+
+/**
+ * Provides a trait for checking the module dependencies of a plugin.
+ */
+trait ModuleDependencyTrait {
+
+  /**
+   * Filter out definitions with unmet module dependencies.
+   *
+   * @param array $definitions
+   *   An array of the available plugin definitions.
+   */
+  protected function filterByModuleDependencies(array &$definitions) {
+    // Get the route just definitions once.
+    $route_definitions = $this->getRouteDefinitions();
+
+    foreach ($definitions as $plugin_id => &$definition) {
+      if (isset($definition['module_dependencies'])) {
+        if (($this->checkModuleDependencies($definition['module_dependencies'])) == FALSE) {
+          unset($definitions[$plugin_id]);
+        }
+      }
+
+      // Include route dependencies on the definitions.
+      if ($route_dependencies = $this->getRouteDependencies($definition, $route_definitions)) {
+        if (($this->checkModuleDependencies($route_dependencies)) == FALSE) {
+          unset($definitions[$plugin_id]);
+        }
+      }
+    }
+  }
+
+  /**
+   * Get all route module dependencies from the existing plugins.
+   *
+   * @param array $definition
+   *   The plugin definition.
+   * @param array $route_definitions
+   *   The defined routes, keyed by provider.
+   *
+   * @return string|null
+   *   The _module dependencies string or null if there's none.
+   *
+   */
+  protected function getRouteDependencies(array $definition, array $route_definitions) {
+//    if (isset($definition['provider']) && isset($route_definitions[$definition['provider']])) {
+    if (isset($definition['provider']) && isset($definition['route_name'])) {
+      return NestedArray::getValue($route_definitions, array($definition['provider'], $definition['route_name'],'requirements', '_module_dependencies'));
+    }
+  }
+
+  /**
+   * Checks whether module dependencies are satisfied.
+   *
+   * @param string $modules
+   *   The list of required modules, separated by a '+' (AND) or ','' (OR).
+   *
+   * @return bool
+   *   TRUE if the dependencies are satisfied, FALSE otherwise.
+   */
+  protected function checkModuleDependencies($modules) {
+    $explode_and = is_array($modules) ? $modules : $this->explodeString($modules, '+');
+    if (count($explode_and) > 1) {
+      foreach ($explode_and as $module) {
+        if (!$this->getModuleHandler()->moduleExists($module)) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    }
+    else {
+      // OR condition, exploding on ',' character.
+      foreach ($this->explodeString($modules, ',') as $module) {
+        if ($this->getModuleHandler()->moduleExists($module)) {
+          return TRUE;
+        }
+      }
+      return FALSE;
+    }
+  }
+
+  /**
+   * Explodes a string based on a separator.
+   *
+   * @param string $string
+   *   The string to explode.
+   * @param string $separator
+   *   The string separator to explode with.
+   *
+   * @return array
+   *   An array of exploded (and trimmed) values.
+   */
+  protected function explodeString($string, $separator = ',') {
+    return array_filter(array_map('trim', explode($separator, $string)));
+  }
+
+  /**
+   * Returns the module handler.
+   *
+   * @return \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler.
+   */
+  protected function getModuleHandler() {
+    // If the class has an injected module handler, use it. Otherwise fall back
+    // to fetch it from the service container.
+    if (isset($this->moduleHandler)) {
+      return $this->moduleHandler;
+    }
+    return \Drupal::moduleHandler();
+  }
+
+  /**
+   * Sets the module handler.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   *
+   * @return $this
+   */
+  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+
+    return $this;
+  }
+
+  /**
+   * Retrieves all defined routes from .routing.yml files.
+   *
+   * @return array
+   *   The defined routes, keyed by provider.
+   */
+  protected function getRouteDefinitions() {
+    if (!isset($this->yamlDiscovery)) {
+      $this->yamlDiscovery = new YamlDiscovery('routing', $this->getModuleHandler()->getModuleDirectories());
+    }
+    return $this->yamlDiscovery->findAll();
+  }
+
+}
diff --git a/core/modules/system/src/Tests/Menu/MenuLinkDependencyTest.php b/core/modules/system/src/Tests/Menu/MenuLinkDependencyTest.php
new file mode 100644
index 0000000..f8c69c1
--- /dev/null
+++ b/core/modules/system/src/Tests/Menu/MenuLinkDependencyTest.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Menu\MenuLinkDependencyTest.
+ */
+
+namespace Drupal\system\Tests\Menu;
+
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests menu router and default menu link functionality.
+ *
+ * @group Menu
+ */
+class MenuLinkDependencyTest extends KernelTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['menu_dependency_test'];
+
+  /**
+   * Test menu link dependencies.
+   */
+  public function testMenuLinkDependency() {
+    /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
+    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
+    $definitions = $menu_link_manager->getDefinitions();
+    $this->assertTrue(empty($definitions['menu_dependency_test.dependency']), 'A menu link with unmet dependencies is not found.');
+
+    \Drupal::service('module_installer')->install(['system', 'menu_ui']);
+    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
+    $definitions = $menu_link_manager->getDefinitions();
+    $this->assertTrue(!empty($definitions['menu_dependency_test.dependency']), 'Menu link is found when the dependent module is enabled.');
+  }
+
+  /**
+   * Test route dependencies.
+   */
+  public function testMenuLinkRouteDependency() {
+    /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
+    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
+    $definitions = $menu_link_manager->getDefinitions();
+    $this->assertTrue(empty($definitions['menu_dependency_test.route_dependency']), 'A menu link with route unmet dependencies is not found.');
+
+    \Drupal::service('module_installer')->install(['system', 'menu_ui']);
+    $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
+    $definitions = $menu_link_manager->getDefinitions();
+    $this->assertTrue(!empty($definitions['menu_dependency_test.route_dependency']), 'Menu link route is found when the dependent module is enabled.');
+  }
+
+}
diff --git a/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.info.yml b/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.info.yml
new file mode 100644
index 0000000..a9edd5c
--- /dev/null
+++ b/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Menu dependency tests'
+type: module
+description: 'Support module for menu dependency testing.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.links.menu.yml b/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.links.menu.yml
new file mode 100644
index 0000000..cc097f9
--- /dev/null
+++ b/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.links.menu.yml
@@ -0,0 +1,8 @@
+menu_dependency_test.dependency:
+  title: 'Test menu link dependencies'
+  route_name: menu_dependency_test.menu_dependency_test
+  module_dependencies: 'menu_ui'
+
+menu_dependency_test.route_dependency:
+  title: 'Test menu link dependencies'
+  route_name: menu_dependency_test.menu_dependency_route_test
diff --git a/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.routing.yml b/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.routing.yml
new file mode 100644
index 0000000..19bf39b
--- /dev/null
+++ b/core/modules/system/tests/modules/menu_dependency_test/menu_dependency_test.routing.yml
@@ -0,0 +1,14 @@
+menu_dependency_test.menu_dependency_test:
+  path: '/menu-dependency-test/dependency'
+  defaults:
+    _content: '\Drupal\menu_dependency_test\Controller\MenuDependencyTestController::menuDependencyTestCallback'
+  requirements:
+    _access: 'TRUE'
+
+menu_dependency_test.menu_dependency_route_test:
+  path: '/menu-dependency-test/route-dependency'
+  defaults:
+    _content: '\Drupal\menu_dependency_test\Controller\MenuDependencyTestController::menuDependencyTestCallback'
+  requirements:
+    _access: 'TRUE'
+    _module_dependencies: 'menu_ui'
diff --git a/core/modules/system/tests/modules/menu_dependency_test/src/Controller/MenuDependencyTestController.php b/core/modules/system/tests/modules/menu_dependency_test/src/Controller/MenuDependencyTestController.php
new file mode 100644
index 0000000..9729a20
--- /dev/null
+++ b/core/modules/system/tests/modules/menu_dependency_test/src/Controller/MenuDependencyTestController.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_dependency_test\Controller\MenuDependencyTestController.
+ */
+
+namespace Drupal\menu_dependency_test\Controller;
+use Drupal\Core\Controller\ControllerBase;
+
+/**
+ * Controller routines for menu_dependency_test routes.
+ */
+class MenuDependencyTestController extends ControllerBase {
+
+  /**
+   * Callback for menu_dependency_test routes.
+   */
+  public function menuDependencyTestCallback() {
+    return $this->t('Menu dependency test callback.');
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Plugin/ModuleDependencyTraitTest.php b/core/tests/Drupal/Tests/Core/Plugin/ModuleDependencyTraitTest.php
new file mode 100644
index 0000000..8bf4d4a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Plugin/ModuleDependencyTraitTest.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Plugin\ModuleDependencyTraitTest.
+ */
+
+namespace Drupal\Tests\Core\Plugin;
+
+use Drupal\Core\Plugin\ModuleDependencyTrait;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the module dependency trait.
+ *
+ * @group Plugin
+ *
+ * @coversDefaultClass \Drupal\Core\Plugin\ModuleDependencyTrait
+ */
+class ModuleDependencyTraitTest extends UnitTestCase {
+
+  /**
+   * Tests the filtering.
+   *
+   * @covers ::filterByModuleDependencies
+   * @covers ::checkModuleDependencies
+   * @covers ::explodeString
+   * @covers ::getModuleHandler
+   * @covers ::setModuleHandler
+   */
+  public function testFilterByModuleDependencies() {
+    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
+    $module_handler->expects($this->any())
+      ->method('moduleExists')
+      ->willReturnMap([
+        ['existing_module', TRUE],
+        ['existing_module2', TRUE],
+        ['not_existing_module', FALSE],
+      ]);
+
+    $test_plugin_manager = new ModuleDependencyTestPluginManager();
+    $test_plugin_manager->setModuleHandler($module_handler);
+
+    $test_definition = [];
+    // Just a single module dependency.
+    $test_definition['plugin_1'] = [
+      'id' => 'plugin_1',
+      'provider' => 'test_module',
+      'module_dependencies' => 'existing_module'
+    ];
+    // Multiple connected via AND.
+    $test_definition['plugin_2'] = [
+      'id' => 'plugin_2',
+      'provider' => 'test_module',
+      'module_dependencies' => 'existing_module+existing_module2',
+    ];
+    // An array of module dependencies.
+    $test_definition['plugin_3'] = [
+      'id' => 'plugin_3',
+      'provider' => 'test_module',
+      'module_dependencies' => ['existing_module', 'existing_module2']
+    ];
+    // One missing module.
+    $test_definition['plugin_4'] = [
+      'id' => 'plugin_4',
+      'provider' => 'test_module',
+      'module_dependencies' => 'existing_module+not_existing_module',
+    ];
+    // Multiple connected via OR.
+    $test_definition['plugin_5'] = [
+      'id' => 'plugin_5',
+      'provider' => 'test_module',
+      'module_dependencies' => 'existing_module,not_existing_module',
+    ];
+
+    $test_plugin_manager->runFilterByModuleDependencies($test_definition);
+
+    $this->assertCount(4, $test_definition);
+    $this->assertEquals(['plugin_1', 'plugin_2', 'plugin_3', 'plugin_5'], array_keys($test_definition));
+  }
+
+}
+
+class ModuleDependencyTestPluginManager {
+
+  use ModuleDependencyTrait;
+
+  public function runFilterByModuleDependencies(array &$definitions) {
+    return $this->filterByModuleDependencies($definitions);
+  }
+
+}
