diff --git a/core/core.services.yml b/core/core.services.yml
index afccb31..5f17972 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -468,7 +468,7 @@ services:
     class: Drupal\Core\Extension\ModuleInstaller
     tags:
       - { name: service_collector, tag: 'module_install.uninstall_validator', call: addUninstallValidator }
-    arguments: ['@app.root', '@module_handler', '@kernel']
+    arguments: ['@app.root', '@module_handler', '@kernel', '@config.factory', '@config.installer', '@config.manager', '@plugin.cache_clearer', '@update.post_update_registry', '@stream_wrapper_manager', '@router.builder', '@logger.factory', '@keyvalue.expirable']
     lazy: true
   content_uninstall_validator:
     class: Drupal\Core\Entity\ContentUninstallValidator
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index f8300cb..fa80d03 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -10,9 +10,18 @@
 use Drupal\Component\Serialization\Yaml;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\ConfigInstallerInterface;
+use Drupal\Core\Config\ConfigManagerInterface;
 use Drupal\Core\DrupalKernelInterface;
 use Drupal\Core\Entity\EntityStorageException;
 use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
+use Drupal\Core\Logger\LoggerChannelFactoryInterface;
+use Drupal\Core\Plugin\CachedDiscoveryClearerInterface;
+use Drupal\Core\Routing\RouteBuilderInterface;
+use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
+use Drupal\Core\Update\UpdateRegistry;
 
 /**
  * Default implementation of the module installer.
@@ -51,6 +60,56 @@ class ModuleInstaller implements ModuleInstallerInterface {
   protected $uninstallValidators;
 
   /**
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * @var \Drupal\Core\Config\ConfigInstallerInterface
+   */
+  protected $configInstaller;
+
+  /**
+   * @var \Drupal\Core\Config\ConfigManagerInterface
+   */
+  protected $configManager;
+
+  /**
+   * @var \Drupal\Core\Plugin\CachedDiscoveryClearerInterface
+   */
+  protected $pluginCacheClearer;
+
+  /**
+   * @var \Drupal\Core\Update\UpdateRegistry
+   */
+  protected $postUpdateRegistry;
+
+  /**
+   * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
+   */
+  protected $streamWrapperManager;
+
+  /**
+   * @var \Drupal\Core\Routing\RouteBuilderInterface
+   */
+  protected $routeBuilder;
+
+  /**
+   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
+   */
+  protected $loggerFactory;
+
+  /**
+   * @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface
+   */
+  protected $keyValueFactory;
+
+  /**
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
    * Constructs a new ModuleInstaller instance.
    *
    * @param string $root
@@ -59,14 +118,33 @@ class ModuleInstaller implements ModuleInstallerInterface {
    *   The module handler.
    * @param \Drupal\Core\DrupalKernelInterface $kernel
    *   The drupal kernel.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   * @param \Drupal\Core\Config\ConfigInstallerInterface $config_installer
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   * @param \Drupal\Core\Plugin\CachedDiscoveryClearerInterface $plugin_cache_clearer
+   * @param \Drupal\Core\Update\UpdateRegistry $post_update_registry
+   * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager
+   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
+   * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory
+   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory
    *
    * @see \Drupal\Core\DrupalKernel
    * @see \Drupal\Core\CoreServiceProvider
    */
-  public function __construct($root, ModuleHandlerInterface $module_handler, DrupalKernelInterface $kernel) {
+  public function __construct($root, ModuleHandlerInterface $module_handler, DrupalKernelInterface $kernel, ConfigFactoryInterface $config_factory, ConfigInstallerInterface $config_installer, ConfigManagerInterface $config_manager, CachedDiscoveryClearerInterface $plugin_cache_clearer, UpdateRegistry $post_update_registry, StreamWrapperManagerInterface $stream_wrapper_manager, RouteBuilderInterface $route_builder, LoggerChannelFactoryInterface $logger_factory, KeyValueFactoryInterface $key_value_factory) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->kernel = $kernel;
+
+    $this->configFactory = $config_factory;
+    $this->configInstaller = $config_installer;
+    $this->configManager = $config_manager;
+    $this->pluginCacheClearer = $plugin_cache_clearer;
+    $this->postUpdateRegistry = $post_update_registry;
+    $this->streamWrapperManager = $stream_wrapper_manager;
+    $this->routeBuilder = $route_builder;
+    $this->loggerFactory = $logger_factory;
+    $this->keyValueFactory = $key_value_factory;
   }
 
   /**
@@ -80,7 +158,7 @@ public function addUninstallValidator(ModuleUninstallValidatorInterface $uninsta
    * {@inheritdoc}
    */
   public function install(array $module_list, $enable_dependencies = TRUE) {
-    $extension_config = \Drupal::configFactory()->getEditable('core.extension');
+    $extension_config = $this->configFactory->getEditable('core.extension');
     if ($enable_dependencies) {
       // Get all module data so we can find dependencies and sort.
       $module_data = system_rebuild_module_data();
@@ -126,11 +204,9 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
     // Required for module installation checks.
     include_once $this->root . '/core/includes/install.inc';
 
-    /** @var \Drupal\Core\Config\ConfigInstaller $config_installer */
-    $config_installer = \Drupal::service('config.installer');
-    $sync_status = $config_installer->isSyncing();
+    $sync_status = $this->configInstaller->isSyncing();
     if ($sync_status) {
-      $source_storage = $config_installer->getSourceStorage();
+      $source_storage = $this->configInstaller->getSourceStorage();
     }
     $modules_installed = array();
     foreach ($module_list as $module) {
@@ -143,7 +219,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
 
         // Check the validity of the default configuration. This will throw
         // exceptions if the configuration is not valid.
-        $config_installer->checkConfigurationToInstall('module', $module);
+        $this->configInstaller->checkConfigurationToInstall('module', $module);
 
         // Save this data without checking schema. This is a performance
         // improvement for module installation.
@@ -202,7 +278,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         drupal_install_schema($module);
 
         // Clear plugin manager caches.
-        \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions();
+        $this->pluginCacheClearer->clearCachedDefinitions();
 
         // Set the schema version to the number of the last update provided by
         // the module, or the minimum core schema version.
@@ -212,45 +288,15 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
           $version = max(max($versions), $version);
         }
 
-        // Notify interested components that this module's entity types and
-        // field storage definitions are new. For example, a SQL-based storage
-        // handler can use this as an opportunity to create the necessary
-        // database tables.
-        // @todo Clean this up in https://www.drupal.org/node/2350111.
-        $entity_manager = \Drupal::entityManager();
-        $update_manager = \Drupal::entityDefinitionUpdateManager();
-        foreach ($entity_manager->getDefinitions() as $entity_type) {
-          if ($entity_type->getProvider() == $module) {
-            $update_manager->installEntityType($entity_type);
-          }
-          elseif ($entity_type->isSubclassOf(FieldableEntityInterface::CLASS)) {
-            // The module being installed may be adding new fields to existing
-            // entity types. Field definitions for any entity type defined by
-            // the module are handled in the if branch.
-            foreach ($entity_manager->getFieldStorageDefinitions($entity_type->id()) as $storage_definition) {
-              if ($storage_definition->getProvider() == $module) {
-                // If the module being installed is also defining a storage key
-                // for the entity type, the entity schema may not exist yet. It
-                // will be created later in that case.
-                try {
-                  $update_manager->installFieldStorageDefinition($storage_definition->getName(), $entity_type->id(), $module, $storage_definition);
-                }
-                catch (EntityStorageException $e) {
-                  watchdog_exception('system', $e, 'An error occurred while notifying the creation of the @name field storage definition: "!message" in %function (line %line of %file).', ['@name' => $storage_definition->getName()]);
-                }
-              }
-            }
-          }
-        }
+        $this->doEntityInstall($module);
 
         // Install default configuration of the module.
-        $config_installer = \Drupal::service('config.installer');
         if ($sync_status) {
-          $config_installer
+          $this->configInstaller
             ->setSyncing(TRUE)
             ->setSourceStorage($source_storage);
         }
-        \Drupal::service('config.installer')->installDefaultConfig('module', $module);
+        $this->configInstaller->installDefaultConfig('module', $module);
 
         // If the module has no current updates, but has some that were
         // previously removed, set the version to the value of
@@ -261,9 +307,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         drupal_set_installed_schema_version($module, $version);
 
         // Ensure that all post_update functions are registered already.
-        /** @var \Drupal\Core\Update\UpdateRegistry $post_update_registry */
-        $post_update_registry = \Drupal::service('update.post_update_registry');
-        $post_update_registry->registerInvokedUpdates($post_update_registry->getModuleUpdateFunctions($module));
+        $this->postUpdateRegistry->registerInvokedUpdates($this->postUpdateRegistry->getModuleUpdateFunctions($module));
 
         // Record the fact that it was installed.
         $modules_installed[] = $module;
@@ -273,28 +317,25 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         // particular, this happens when installing Drupal via Drush, as the
         // 'translations' stream wrapper is provided by Interface Translation
         // module and is later used to import translations.
-        \Drupal::service('stream_wrapper_manager')->register();
+        $this->streamWrapperManager->register();
 
         // Update the theme registry to include it.
         drupal_theme_rebuild();
 
         // Modules can alter theme info, so refresh theme data.
-        // @todo ThemeHandler cannot be injected into ModuleHandler, since that
-        //   causes a circular service dependency.
-        // @see https://www.drupal.org/node/2208429
-        \Drupal::service('theme_handler')->refreshInfo();
+        $this->themeHandler()->refreshInfo();
 
         // Allow the module to perform install tasks.
         $this->moduleHandler->invoke($module, 'install');
 
         // Record the fact that it was installed.
-        \Drupal::logger('system')->info('%module module installed.', array('%module' => $module));
+        $this->loggerFactory->get('system')->info('%module module installed.', array('%module' => $module));
       }
     }
 
     // If any modules were newly installed, invoke hook_modules_installed().
     if (!empty($modules_installed)) {
-      \Drupal::service('router.builder')->setRebuildNeeded();
+      $this->routeBuilder->setRebuildNeeded();
       $this->moduleHandler->invokeAll('modules_installed', array($modules_installed));
     }
 
@@ -302,6 +343,42 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
   }
 
   /**
+   * @todo.
+   */
+  protected function doEntityInstall($module) {
+    // Notify interested components that this module's entity types and
+    // field storage definitions are new. For example, a SQL-based storage
+    // handler can use this as an opportunity to create the necessary
+    // database tables.
+    // @todo Clean this up in https://www.drupal.org/node/2350111.
+    $update_manager = \Drupal::entityDefinitionUpdateManager();
+    $entity_field_manager = \Drupal::service('entity_field.manager');
+    foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type) {
+      if ($entity_type->getProvider() == $module) {
+        $update_manager->installEntityType($entity_type);
+      }
+      elseif ($entity_type->isSubclassOf(FieldableEntityInterface::CLASS)) {
+        // The module being installed may be adding new fields to existing
+        // entity types. Field definitions for any entity type defined by
+        // the module are handled in the if branch.
+        foreach ($entity_field_manager->getFieldStorageDefinitions($entity_type->id()) as $storage_definition) {
+          if ($storage_definition->getProvider() == $module) {
+            // If the module being installed is also defining a storage key
+            // for the entity type, the entity schema may not exist yet. It
+            // will be created later in that case.
+            try {
+              $update_manager->installFieldStorageDefinition($storage_definition->getName(), $entity_type->id(), $module, $storage_definition);
+            }
+            catch (EntityStorageException $e) {
+              watchdog_exception('system', $e, 'An error occurred while notifying the creation of the @name field storage definition: "!message" in %function (line %line of %file).', ['@name' => $storage_definition->getName()]);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
@@ -313,7 +390,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
       return FALSE;
     }
 
-    $extension_config = \Drupal::configFactory()->getEditable('core.extension');
+    $extension_config = $this->configFactory->getEditable('core.extension');
     $installed_modules = $extension_config->get('module') ?: array();
     if (!$module_list = array_intersect_key($module_list, $installed_modules)) {
       // Nothing to do. All modules already uninstalled.
@@ -361,17 +438,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
     // necessarily installed.
     foreach ($module_list as $module) {
 
-      // Clean up all entity bundles (including fields) of every entity type
-      // provided by the module that is being uninstalled.
-      // @todo Clean this up in https://www.drupal.org/node/2350111.
-      $entity_manager = \Drupal::entityManager();
-      foreach ($entity_manager->getDefinitions() as $entity_type_id => $entity_type) {
-        if ($entity_type->getProvider() == $module) {
-          foreach (array_keys($entity_manager->getBundleInfo($entity_type_id)) as $bundle) {
-            $entity_manager->onBundleDelete($bundle, $entity_type_id);
-          }
-        }
-      }
+      $this->doEntityPreUninstall($module);
 
       // Allow modules to react prior to the uninstallation of a module.
       $this->moduleHandler->invokeAll('module_preuninstall', array($module));
@@ -381,40 +448,16 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
       $this->moduleHandler->invoke($module, 'uninstall');
 
       // Remove all configuration belonging to the module.
-      \Drupal::service('config.manager')->uninstall('module', $module);
+      $this->configManager->uninstall('module', $module);
 
-      // Notify interested components that this module's entity types are being
-      // deleted. For example, a SQL-based storage handler can use this as an
-      // opportunity to drop the corresponding database tables.
-      // @todo Clean this up in https://www.drupal.org/node/2350111.
-      $update_manager = \Drupal::entityDefinitionUpdateManager();
-      foreach ($entity_manager->getDefinitions() as $entity_type) {
-        if ($entity_type->getProvider() == $module) {
-          $update_manager->uninstallEntityType($entity_type);
-        }
-        elseif ($entity_type->isSubclassOf(FieldableEntityInterface::CLASS)) {
-          // The module being installed may be adding new fields to existing
-          // entity types. Field definitions for any entity type defined by
-          // the module are handled in the if branch.
-          $entity_type_id = $entity_type->id();
-          /** @var \Drupal\Core\Entity\FieldableEntityStorageInterface $storage */
-          $storage = $entity_manager->getStorage($entity_type_id);
-          foreach ($entity_manager->getFieldStorageDefinitions($entity_type_id) as $storage_definition) {
-            // @todo We need to trigger field purging here.
-            //   See https://www.drupal.org/node/2282119.
-            if ($storage_definition->getProvider() == $module && !$storage->countFieldData($storage_definition, TRUE)) {
-              $update_manager->uninstallFieldStorageDefinition($storage_definition);
-            }
-          }
-        }
-      }
+      $this->doEntityUninstall($module);
 
       // Remove the schema.
       drupal_uninstall_schema($module);
 
       // Remove the module's entry from the config. Don't check schema when
       // uninstalling a module since we are only clearing a key.
-      \Drupal::configFactory()->getEditable('core.extension')->clear("module.$module")->save(TRUE);
+      $this->configFactory->getEditable('core.extension')->clear("module.$module")->save(TRUE);
 
       // Update the module handler to remove the module.
       // The current ModuleHandler instance is obsolete with the kernel rebuild
@@ -432,7 +475,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
       drupal_static_reset('system_rebuild_module_data');
 
       // Clear plugin manager caches.
-      \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions();
+      $this->pluginCacheClearer->clearCachedDefinitions();
 
       // Update the kernel to exclude the uninstalled modules.
       $this->updateKernel($module_filenames);
@@ -441,21 +484,16 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
       drupal_theme_rebuild();
 
       // Modules can alter theme info, so refresh theme data.
-      // @todo ThemeHandler cannot be injected into ModuleHandler, since that
-      //   causes a circular service dependency.
-      // @see https://www.drupal.org/node/2208429
-      \Drupal::service('theme_handler')->refreshInfo();
+      $this->themeHandler()->refreshInfo();
 
-      \Drupal::logger('system')->info('%module module uninstalled.', array('%module' => $module));
+      $this->loggerFactory->get('system')->info('%module module uninstalled.', array('%module' => $module));
 
-      $schema_store = \Drupal::keyValue('system.schema');
+      $schema_store = $this->keyValueFactory->get('system.schema');
       $schema_store->delete($module);
 
-      /** @var \Drupal\Core\Update\UpdateRegistry $post_update_registry */
-      $post_update_registry = \Drupal::service('update.post_update_registry');
-      $post_update_registry->filterOutInvokedUpdatesByModule($module);
+      $this->postUpdateRegistry->filterOutInvokedUpdatesByModule($module);
     }
-    \Drupal::service('router.builder')->setRebuildNeeded();
+    $this->routeBuilder->setRebuildNeeded();
     drupal_get_installed_schema_version(NULL, TRUE);
 
     // Let other modules react.
@@ -473,6 +511,57 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
   }
 
   /**
+   * @todo.
+   */
+  protected function doEntityPreUninstall($module) {
+    // Clean up all entity bundles (including fields) of every entity type
+    // provided by the module that is being uninstalled.
+    // @todo Clean this up in https://www.drupal.org/node/2350111.
+    $entity_type_bundle_info = \Drupal::service('entity_type.bundle.info');
+    $entity_bundle_listener = \Drupal::service('entity_bundle.listener');
+    foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type_id => $entity_type) {
+      if ($entity_type->getProvider() == $module) {
+        foreach (array_keys($entity_type_bundle_info->getBundleInfo($entity_type_id)) as $bundle) {
+          $entity_bundle_listener->onBundleDelete($bundle, $entity_type_id);
+        }
+      }
+    }
+  }
+
+  /**
+   * @todo.
+   */
+  protected function doEntityUninstall($module) {
+    // Notify interested components that this module's entity types are being
+    // deleted. For example, a SQL-based storage handler can use this as an
+    // opportunity to drop the corresponding database tables.
+    // @todo Clean this up in https://www.drupal.org/node/2350111.
+    $entity_type_manager = \Drupal::entityTypeManager();
+    $update_manager = \Drupal::entityDefinitionUpdateManager();
+    $entity_field_manager = \Drupal::service('entity_field.manager');
+    foreach ($entity_type_manager->getDefinitions() as $entity_type) {
+      if ($entity_type->getProvider() == $module) {
+        $update_manager->uninstallEntityType($entity_type);
+      }
+      elseif ($entity_type->isSubclassOf(FieldableEntityInterface::CLASS)) {
+        // The module being installed may be adding new fields to existing
+        // entity types. Field definitions for any entity type defined by
+        // the module are handled in the if branch.
+        $entity_type_id = $entity_type->id();
+        /** @var \Drupal\Core\Entity\FieldableEntityStorageInterface $storage */
+        $storage = $entity_type_manager->getStorage($entity_type_id);
+        foreach ($entity_field_manager->getFieldStorageDefinitions($entity_type_id) as $storage_definition) {
+          // @todo We need to trigger field purging here.
+          //   See https://www.drupal.org/node/2282119.
+          if ($storage_definition->getProvider() == $module && !$storage->countFieldData($storage_definition, TRUE)) {
+            $update_manager->uninstallFieldStorageDefinition($storage_definition);
+          }
+        }
+      }
+    }
+  }
+
+  /**
    * Helper method for removing all cache bins registered by a given module.
    *
    * @param string $module
@@ -484,6 +573,7 @@ protected function removeCacheBins($module) {
     if (file_exists($service_yaml_file)) {
       $definitions = Yaml::decode(file_get_contents($service_yaml_file));
       if (isset($definitions['services'])) {
+        $container = \Drupal::getContainer();
         foreach ($definitions['services'] as $id => $definition) {
           if (isset($definition['tags'])) {
             foreach ($definition['tags'] as $tag) {
@@ -492,7 +582,7 @@ protected function removeCacheBins($module) {
               // be extremely rare.
               if ($tag['name'] == 'cache.bin' && isset($definition['factory_service']) && isset($definition['factory_method']) && !empty($definition['arguments'])) {
                 try {
-                  $factory = \Drupal::service($definition['factory_service']);
+                  $factory = $container->get($definition['factory_service']);
                   if (method_exists($factory, $definition['factory_method'])) {
                     $backend = call_user_func_array(array($factory, $definition['factory_method']), $definition['arguments']);
                     if ($backend instanceof CacheBackendInterface) {
@@ -548,4 +638,18 @@ public function validateUninstall(array $module_list) {
     return $reasons;
   }
 
+  /**
+   * Wraps the theme handler service.
+   *
+   * @todo ThemeHandler cannot be injected into ModuleHandler, since that
+   *   causes a circular service dependency.
+   * @see https://www.drupal.org/node/2208429
+   */
+  protected function themeHandler() {
+    if (!$this->themeHandler) {
+      $this->themeHandler = \Drupal::service('theme_handler');
+    }
+    return $this->themeHandler;
+  }
+
 }
