diff --git a/core/core.services.yml b/core/core.services.yml
index 6049d3b..7b0e996 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -396,6 +396,9 @@ services:
   logger.channel.form:
     parent: logger.channel_base
     arguments: ['form']
+  logger.channel.system:
+    parent: logger.channel_base
+    arguments: ['system']
   logger.log_message_parser:
     class: Drupal\Core\Logger\LogMessageParser
 
@@ -476,6 +479,7 @@ services:
     arguments: ['@app.root', '%container.modules%', '@cache.bootstrap']
   module_installer:
     class: Drupal\Core\Extension\ModuleInstaller
+    arguments: ['@app.root', '@module_handler', '@kernel', '@config.factory', '@config.installer', '@plugin.cache_clearer', '@router.builder', '@stream_wrapper_manager', '@theme_handler', '@logger.channel.system', '@config.manager', '@keyvalue']
     tags:
       - { name: service_collector, tag: 'module_install.uninstall_validator', call: addUninstallValidator }
     arguments: ['@app.root', '@module_handler', '@kernel', '@router.builder']
diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateDependenciesTrait.php b/core/lib/Drupal/Core/DependencyInjection/UpdateDependenciesTrait.php
new file mode 100644
index 0000000..3c8be15
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/UpdateDependenciesTrait.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Drupal\Core\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a trait which automatically updates dependencies from the container.
+ *
+ * Classes which trigger a container rebuild should point to the instances of
+ * the services with the new container. Calling the ::updateDependencies()
+ * method takes care of that.
+ *
+ * If the service depends on container parameters and if they can possibly
+ * change then the service will need to handle this itself.
+ */
+trait UpdateDependenciesTrait {
+
+  /**
+   * Updates an object's external dependencies from the container.
+   *
+   * This method depends on \Drupal\Core\DependencyInjection\Container::get()
+   * adding the _serviceId property to all services.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+   *   The container.
+   *
+   * @see \Drupal\Core\DependencyInjection\Container
+   */
+  protected function updateDependencies(ContainerInterface $container) {
+    $vars = get_object_vars($this);
+    foreach ($vars as $key => $value) {
+      if (is_object($value) && isset($value->_serviceId)) {
+        $this->$key = $container->get($value->_serviceId);
+      }
+      // Special case the container, which might not have a service ID.
+      elseif ($value instanceof ContainerInterface) {
+        $this->$key = $container;
+      }
+    }
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index a903b8a..8da0dcf 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -5,9 +5,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\DependencyInjection\UpdateDependenciesTrait;
 use Drupal\Core\DrupalKernelInterface;
 use Drupal\Core\Entity\EntityStorageException;
 use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
+use Drupal\Core\Plugin\CachedDiscoveryClearerInterface;
+use Drupal\Core\Routing\RouteBuilderInterface;
+use Drupal\Core\StreamWrapper\StreamWrapperManager;
+use Psr\Log\LoggerInterface;
 
 /**
  * Default implementation of the module installer.
@@ -17,6 +26,8 @@
  */
 class ModuleInstaller implements ModuleInstallerInterface {
 
+  use UpdateDependenciesTrait;
+
   /**
    * The module handler.
    *
@@ -46,6 +57,69 @@ class ModuleInstaller implements ModuleInstallerInterface {
   protected $uninstallValidators;
 
   /**
+   * The config factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The config installer.
+   *
+   * @var \Drupal\Core\Config\ConfigInstallerInterface
+   */
+  protected $configInstaller;
+
+  /**
+   * The plugin cache clearer.
+   *
+   * @var \Drupal\Core\Plugin\CachedDiscoveryClearerInterface
+   */
+  protected $pluginCacheClearer;
+
+  /**
+   * The route builder.
+   *
+   * @var \Drupal\Core\Routing\RouteBuilderInterface
+   */
+  protected $routeBuilder;
+
+  /**
+   * The stream wrapper manager.
+   *
+   * @var \Drupal\Core\StreamWrapper\StreamWrapperManager
+   */
+  protected $streamWrapperManager;
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * The logger.
+   *
+   * @var \Psr\Log\LoggerInterface
+   */
+  protected $logger;
+
+  /**
+   * The config manager.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface
+   */
+  protected $configManager;
+
+  /**
+   * The key value factory.
+   *
+   * @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface
+   */
+  protected $keyValueFactory;
+
+  /**
    * Constructs a new ModuleInstaller instance.
    *
    * @param string $root
@@ -54,14 +128,41 @@ class ModuleInstaller implements ModuleInstallerInterface {
    *   The module handler.
    * @param \Drupal\Core\DrupalKernelInterface $kernel
    *   The drupal kernel.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   * @param \Drupal\Core\Config\ConfigInstallerInterface $config_installer
+   *   The config installer.
+   * @param \Drupal\Core\Plugin\CachedDiscoveryClearerInterface $plugin_cache_clearer
+   *   The plugin cache clearer.
+   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
+   *   The route builder.
+   * @param \Drupal\Core\StreamWrapper\StreamWrapperManager $stream_wrapper_manager
+   *   The stream wrapper manager.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler.
+   * @param \Psr\Log\LoggerInterface $logger
+   *   The logger.
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   *   The config manager.
+   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory
+   *   The 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, CachedDiscoveryClearerInterface $plugin_cache_clearer, RouteBuilderInterface $route_builder, StreamWrapperManager $stream_wrapper_manager, ThemeHandlerInterface $theme_handler, LoggerInterface $logger, ConfigManagerInterface $config_manager, KeyValueFactoryInterface $key_value_factory) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->kernel = $kernel;
+    $this->configFactory = $config_factory;
+    $this->configInstaller = $config_installer;
+    $this->pluginCacheClearer = $plugin_cache_clearer;
+    $this->routeBuilder = $route_builder;
+    $this->streamWrapperManager = $stream_wrapper_manager;
+    $this->themeHandler = $theme_handler;
+    $this->logger = $logger;
+    $this->configManager = $config_manager;
+    $this->keyValueFactory = $key_value_factory;
   }
 
   /**
@@ -75,7 +176,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();
@@ -121,11 +222,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) {
@@ -138,7 +237,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.
@@ -197,7 +296,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.
@@ -239,13 +338,12 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         }
 
         // 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
@@ -268,16 +366,13 @@ 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();
 
         // In order to make uninstalling transactional if anything uses routes.
         \Drupal::getContainer()->set('router.route_provider.old', \Drupal::service('router.route_provider'));
@@ -287,7 +382,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         $this->moduleHandler->invoke($module, 'install');
 
         // Record the fact that it was installed.
-        \Drupal::logger('system')->info('%module module installed.', array('%module' => $module));
+        $this->logger->info('%module module installed.', array('%module' => $module));
       }
     }
 
@@ -320,7 +415,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.
@@ -388,7 +483,7 @@ 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);
 
       // In order to make uninstalling transactional if anything uses routes.
       \Drupal::getContainer()->set('router.route_provider.old', \Drupal::service('router.route_provider'));
@@ -425,7 +520,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
 
       // 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
@@ -443,7 +538,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);
@@ -452,15 +547,11 @@ 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->logger->info('%module module uninstalled.', array('%module' => $module));
 
-      $schema_store = \Drupal::keyValue('system.schema');
-      $schema_store->delete($module);
+      $this->keyValueFactory->get('system.schema')->delete($module);
 
       /** @var \Drupal\Core\Update\UpdateRegistry $post_update_registry */
       $post_update_registry = \Drupal::service('update.post_update_registry');
@@ -470,7 +561,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
     // \Drupal\Core\Routing\RouteBuilder::destruct to not run into errors on
     // fastCGI which executes ::destruct() after the Module uninstallation page
     // was sent already.
-    \Drupal::service('router.builder')->rebuild();
+    $this->routeBuilder->rebuild();
     drupal_get_installed_schema_version(NULL, TRUE);
 
     // Let other modules react.
@@ -540,8 +631,7 @@ protected function updateKernel($module_filenames) {
     $this->kernel->updateModules($module_filenames, $module_filenames);
     // After rebuilding the container we need to update the injected
     // dependencies.
-    $container = $this->kernel->getContainer();
-    $this->moduleHandler = $container->get('module_handler');
+    $this->updateDependencies($this->kernel->getContainer());
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Module/InstallUninstallTest.php b/core/modules/system/src/Tests/Module/InstallUninstallTest.php
index d8d625b..9f35a54 100644
--- a/core/modules/system/src/Tests/Module/InstallUninstallTest.php
+++ b/core/modules/system/src/Tests/Module/InstallUninstallTest.php
@@ -133,7 +133,7 @@ public function testInstallUninstall() {
       // appropriate messages appear in the logs.
       foreach ($modules_to_install as $module_to_install) {
         $this->assertText(t('hook_modules_installed fired for @module', array('@module' => $module_to_install)));
-        $this->assertLogMessage('system', "%module module installed.", array('%module' => $module_to_install), RfcLogLevel::INFO);
+        $this->assertLogMessage('modules', "%module module installed.", array('%module' => $module_to_install), RfcLogLevel::INFO);
         $this->assertInstallModuleUpdates($module_to_install);
         $this->assertModuleSuccessfullyInstalled($module_to_install);
       }
@@ -255,7 +255,7 @@ protected function assertSuccessfulUninstall($module, $package = 'Core') {
     // module was just uninstalled, since the {watchdog} table won't be there
     // anymore.)
     $this->assertText(t('hook_modules_uninstalled fired for @module', array('@module' => $module)));
-    $this->assertLogMessage('system', "%module module uninstalled.", array('%module' => $module), RfcLogLevel::INFO);
+    $this->assertLogMessage('modules', "%module module uninstalled.", array('%module' => $module), RfcLogLevel::INFO);
 
     // Check that the module's database tables no longer exist.
     $this->assertModuleTablesDoNotExist($module);
diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/UpdateDependenciesTraitTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/UpdateDependenciesTraitTest.php
new file mode 100644
index 0000000..744c61d
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/DependencyInjection/UpdateDependenciesTraitTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\Tests\Core\DependencyInjection;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\DependencyInjection\UpdateDependenciesTrait;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @coversDefaultClass \Drupal\Core\DependencyInjection\UpdateDependenciesTrait
+ * @group DependencyInjection
+ */
+class UpdateDependenciesTraitTest extends UnitTestCase {
+
+  /**
+   * @covers ::updateDependencies
+   */
+  public function testUpdateDependencies() {
+    $service = new \StdClass();
+    $service->_serviceId = 'test_service';
+
+    $container = new ContainerBuilder();
+    $container->set('test_service', $service);
+
+    $trait_test = new UpdateDependenciesTraitTestClass();
+    $trait_test->dependency = clone $service;
+    $trait_test->container = $container;
+
+    $object = new \StdClass();
+    $trait_test->object = $object;
+
+    // Ensure that the service and container are updated but other objects are
+    // untouched.
+    $trait_test->updateDependenciesPublic($container);
+
+    $this->assertSame($service, $trait_test->dependency);
+    $this->assertSame($container, $trait_test->container);
+    $this->assertSame($object, $trait_test->object);
+  }
+
+}
+
+class UpdateDependenciesTraitTestClass {
+
+  use UpdateDependenciesTrait;
+
+  /**
+   * Updates dependencies.
+   *
+   * A wrapper around the protected UpdateDependenciesTrait::updateDependencies
+   * method.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+   */
+  public function updateDependenciesPublic(ContainerInterface $container) {
+    $this->updateDependencies($container);
+  }
+}
