diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 7149004..e84d99c 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -725,13 +725,16 @@ function drupal_settings_initialize() {
   global $base_url, $base_path, $base_root, $script_path;
 
   // Export these settings.php variables to the global namespace.
-  global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directories;
+  global $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directories;
   $conf = array();
 
   // Make conf_path() available as local variable in settings.php.
   $conf_path = conf_path();
   if (is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) {
     include_once DRUPAL_ROOT . '/' . $conf_path . '/settings.php';
+    if (!empty($databases)) {
+      drupal_container()->setParameter('database.info', $databases);
+    }
   }
   $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
 
@@ -2133,14 +2136,14 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
           _drupal_bootstrap_configuration();
           break;
 
-        case DRUPAL_BOOTSTRAP_PAGE_CACHE:
-          _drupal_bootstrap_page_cache();
-          break;
-
         case DRUPAL_BOOTSTRAP_DATABASE:
           _drupal_bootstrap_database();
           break;
 
+        case DRUPAL_BOOTSTRAP_PAGE_CACHE:
+          _drupal_bootstrap_page_cache();
+          break;
+
         case DRUPAL_BOOTSTRAP_VARIABLES:
           _drupal_bootstrap_variables();
           break;
@@ -2242,15 +2245,14 @@ function _drupal_bootstrap_configuration() {
   drupal_environment_initialize();
   // Start a page timer:
   timer_start('page');
+  // Activate the class loader.
+  drupal_classloader();
   // Initialize the configuration, including variables from settings.php.
   drupal_settings_initialize();
 
   // Make sure we are using the test database prefix in child Drupal sites.
   _drupal_initialize_db_test_prefix();
 
-  // Activate the class loader.
-  drupal_classloader();
-
   // Load the procedural configuration system helper functions.
   require_once DRUPAL_ROOT . '/core/includes/config.inc';
 }
@@ -2324,7 +2326,8 @@ function _drupal_initialize_db_test_prefix() {
     $test_info['test_run_id'] = $test_prefix;
     $test_info['in_child_site'] = TRUE;
 
-    foreach ($GLOBALS['databases']['default'] as &$value) {
+    $databases = drupal_container()->getParameter('database.info');
+    foreach ($databases['default'] as &$value) {
       // Extract the current default database prefix.
       if (!isset($value['prefix'])) {
         $current_prefix = '';
@@ -2341,6 +2344,7 @@ function _drupal_initialize_db_test_prefix() {
         'default' => $current_prefix . $test_prefix,
       );
     }
+    drupal_container()->setParameter('database.info', $databases);
   }
 }
 
@@ -2351,12 +2355,14 @@ function _drupal_bootstrap_database() {
   // Redirect the user to the installation script if Drupal has not been
   // installed yet (i.e., if no $databases array has been defined in the
   // settings.php file) and we are not already installing.
-  if (empty($GLOBALS['databases']) && !drupal_installation_attempted()) {
+  if (drupal_container()->hasParameter('database.info')) {
+    $databases = drupal_container()->getParameter('database.info');
+  }
+  if (empty($databases) && !drupal_installation_attempted()) {
     include_once DRUPAL_ROOT . '/core/includes/install.inc';
     install_goto('core/install.php');
   }
 
-
   // Initialize the database system. Note that the connection
   // won't be initialized until it is actually requested.
   require_once DRUPAL_ROOT . '/core/includes/database.inc';
@@ -2441,12 +2447,31 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) {
     $container
       ->register('config.cachedstorage.storage', 'Drupal\Core\Config\FileStorage')
       ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
-    // @todo Replace this with a cache.factory service plus 'config' argument.
-    $container
-      ->register('cache.config')
-      ->setFactoryClass('Drupal\Core\Cache\CacheFactory')
-      ->setFactoryMethod('get')
-      ->addArgument('config');
+
+    // This will be overridden by settings.php in drupal_settings_initialize().
+    $container->setParameter('database.info', array());
+    $container->register('database', 'Drupal\Core\Database\Connection')
+      ->setFactoryClass('Drupal\Core\Database\Database')
+      ->setFactoryMethod('getConnection')
+      ->addArgument('default')
+      ->addArgument(NULL)
+      ->addArgument('%database.info%');
+    $container->register('database.slave', 'Drupal\Core\Database\Connection')
+      ->setFactoryClass('Drupal\Core\Database\Database')
+      ->setFactoryMethod('getConnection')
+      ->addArgument('slave')
+      ->addArgument(NULL)
+      ->addArgument('%database.info%');
+    $container->register('cache', 'Drupal\Core\Cache\DatabaseBackend')
+      ->addArgument('cache')
+      ->addArgument(new Reference('database'))
+      ->addTag('cache');
+    foreach (array('bootstrap', 'config') as $bin) {
+      $container->register('cache.' . $bin, 'Drupal\Core\Cache\DatabaseBackend')
+        ->addArgument($bin)
+        ->addArgument(new Reference('database'))
+        ->addTag('cache');
+    }
 
     $container
       ->register('config.storage', 'Drupal\Core\Config\CachedStorage')
diff --git a/core/includes/cache.inc b/core/includes/cache.inc
index 341d77f..7664858 100644
--- a/core/includes/cache.inc
+++ b/core/includes/cache.inc
@@ -5,16 +5,8 @@
  * Functions and interfaces for cache handling.
  */
 
-use Drupal\Core\Cache\CacheFactory;
-
 /**
- * Instantiates and statically caches the correct class for a cache bin.
- *
- * By default, this returns an instance of the Drupal\Core\Cache\DatabaseBackend
- * class.
- *
- * Classes implementing Drupal\Core\Cache\CacheBackendInterface can register
- * themselves both as a default implementation and for specific bins.
+ * Returns a cache service.
  *
  * @param $bin
  *   The cache bin for which the cache object should be returned, defaults to
@@ -26,21 +18,8 @@
  * @see Drupal\Core\Cache\CacheBackendInterface
  */
 function cache($bin = 'cache') {
-  // Use the advanced drupal_static() pattern, since this is called very often.
-  static $drupal_static_fast;
-  if (!isset($drupal_static_fast)) {
-    $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__, array());
-  }
-  $cache_objects = &$drupal_static_fast['cache'];
-
-  // Temporary backwards compatibiltiy layer, allow old style prefixed cache
-  // bin names to be passed as arguments.
-  $bin = str_replace('cache_', '', $bin);
-
-  if (!isset($cache_objects[$bin])) {
-    $cache_objects[$bin] = CacheFactory::get($bin);
-  }
-  return $cache_objects[$bin];
+  $service = $bin == 'cache' ? 'cache' : 'cache.' . $bin;
+  return drupal_container()->get($service);
 }
 
 /**
@@ -57,7 +36,18 @@ function cache($bin = 'cache') {
  *   The list of tags to invalidate cache items for.
  */
 function cache_invalidate(array $tags) {
-  foreach (CacheFactory::getBackends() as $bin => $class) {
-    cache($bin)->invalidateTags($tags);
+  $container = drupal_container();
+  foreach (cache_backends() as $name) {
+    $container->get($name)->invalidateTags($tags);
   }
 }
+
+/**
+ * Returns a list of cache backends for this site.
+ *
+ * @return array
+ *   An array of cache backend service names.
+ */
+function cache_backends() {
+  return array_keys(drupal_container()->findTaggedServiceIds('cache'));
+}
diff --git a/core/includes/common.inc b/core/includes/common.inc
index b3dc9cb..e87798f 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -4809,10 +4809,10 @@ function drupal_json_decode($var) {
  *   A salt based on information in settings.php, not in the database.
  */
 function drupal_get_hash_salt() {
-  global $drupal_hash_salt, $databases;
+  global $drupal_hash_salt;
   // If the $drupal_hash_salt variable is empty, a hash of the serialized
   // database credentials is used as a fallback salt.
-  return empty($drupal_hash_salt) ? hash('sha256', serialize($databases)) : $drupal_hash_salt;
+  return empty($drupal_hash_salt) ? hash('sha256', serialize(drupal_container()->getParameter('database.info'))) : $drupal_hash_salt;
 }
 
 /**
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index b1d3b50..b3a7ac2 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -346,7 +346,13 @@ function install_begin_request(&$install_state) {
   // because any data put in the cache during the installer is inherently
   // suspect, due to the fact that Drupal is not fully set up yet.
   require_once DRUPAL_ROOT . '/core/includes/cache.inc';
-  $conf['cache_classes'] = array('cache' => 'Drupal\Core\Cache\InstallBackend');
+  $container = drupal_container();
+  $container->register('cache', 'Drupal\Core\Cache\InstallBackend')
+    ->addArgument('cache');
+  $container->register('cache.bootstrap', 'Drupal\Core\Cache\InstallBackend')
+    ->addArgument('bootstrap');
+  $container->register('cache.form', 'Drupal\Core\Cache\InstallBackend')
+    ->addArgument('form');
 
   // The install process cannot use the database lock backend since the database
   // is not fully up, so we use a null backend implementation during the
@@ -372,6 +378,15 @@ function install_begin_request(&$install_state) {
     // Initialize the database system. Note that the connection
     // won't be initialized until it is actually requested.
     require_once DRUPAL_ROOT . '/core/includes/database.inc';
+    $container->register('cache', 'Drupal\Core\Cache\DatabaseBackend')
+      ->addArgument('cache')
+      ->addArgument(new Reference('database'));
+    $container->register('cache.bootstrap', 'Drupal\Core\Cache\DatabaseBackend')
+      ->addArgument('bootstrap')
+      ->addArgument(new Reference('database'));
+    $container->register('cache.form', 'Drupal\Core\Cache\DatabaseBackend')
+      ->addArgument('form')
+      ->addArgument(new Reference('database'));
 
     // Verify the last completed task in the database, if there is one.
     $task = install_verify_completed_task();
@@ -496,7 +511,14 @@ function install_run_task($task, &$install_state) {
         // We need to pass $install_state by reference in order for forms to
         // modify it, since the form API will use it in call_user_func_array(),
         // which requires that referenced variables be passed explicitly.
-        'build_info' => array('args' => array(&$install_state)),
+        'build_info' => array(
+          'args' => array(&$install_state),
+          // drupal_retrieve_form() tries to load the current menu item
+          // if this is not set.
+          'files' => array(
+            'menu' => FALSE,
+          )
+        ),
       );
       drupal_form_submit($function, $form_state);
       $errors = form_get_errors();
@@ -939,8 +961,9 @@ function install_verify_completed_task() {
  * Verifies that settings.php specifies a valid database connection.
  */
 function install_verify_database_settings() {
-  global $databases;
-  if (!empty($databases)) {
+  $container = drupal_container();
+  if ($container->hasParameter('database.info')) {
+    $databases = $container->getParameter('database.info');
     $database = $databases['default']['default'];
     drupal_static_reset('conf_path');
     $settings_file = './' . conf_path(FALSE) . '/settings.php';
@@ -963,13 +986,16 @@ function install_verify_database_settings() {
  * @ingroup forms
  */
 function install_settings_form($form, &$form_state, &$install_state) {
-  global $databases;
   $profile = $install_state['parameters']['profile'];
 
   drupal_static_reset('conf_path');
   $conf_path = './' . conf_path(FALSE);
   $settings_file = $conf_path . '/settings.php';
-  $database = isset($databases['default']['default']) ? $databases['default']['default'] : array();
+  $database = array();
+  if (drupal_container()->hasParameter('database.info')) {
+    $databases = drupal_container()->getParameter('database.info');
+    $database = isset($databases['default']['default']) ? $databases['default']['default'] : array();
+  }
 
   drupal_set_title(st('Database configuration'));
 
@@ -1037,6 +1063,7 @@ function install_settings_form_validate($form, &$form_state) {
   unset($database['db_prefix']);
 
   $form_state['storage']['database'] = $database;
+  drupal_container()->setParameter('database.info', array('default' => $database));
   $errors = install_database_errors($database, $form_state['values']['settings_file']);
   foreach ($errors as $name => $message) {
     form_set_error($name, $message);
@@ -1047,7 +1074,6 @@ function install_settings_form_validate($form, &$form_state) {
  * Checks a database connection and returns any errors.
  */
 function install_database_errors($database, $settings_file) {
-  global $databases;
   $errors = array();
 
   // Check database type.
@@ -1062,17 +1088,15 @@ function install_database_errors($database, $settings_file) {
 
     // Run tasks associated with the database type. Any errors are caught in the
     // calling function.
-    $databases['default']['default'] = $database;
     // Just changing the global doesn't get the new information processed.
     // We need to close any active connections and tell the Database class to
     // re-parse $databases.
     if (Database::isActiveConnection()) {
       Database::closeConnection();
     }
-    Database::parseConnectionInfo();
 
     try {
-      db_run_tasks($driver);
+      db_run_tasks($driver, $database);
     }
     catch (TaskException $e) {
       // These are generic errors, so we do not have any specific key of the
diff --git a/core/includes/install.inc b/core/includes/install.inc
index db92987..9b4441a 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -933,8 +933,8 @@ function install_profile_info($profile, $langcode = 'en') {
  * TABLE to database specific functions like stored procedures and client
  * encoding.
  */
-function db_run_tasks($driver) {
-  db_installer_object($driver)->runTasks();
+function db_run_tasks($driver, $database) {
+  db_installer_object($driver, $database)->runTasks();
   return TRUE;
 }
 
@@ -944,9 +944,9 @@ function db_run_tasks($driver) {
  * @param $driver
  *   The name of the driver.
  */
-function db_installer_object($driver) {
+function db_installer_object($driver, $database = NULL) {
   // We cannot use Database::getConnection->getDriverClass() here, because
   // the connection object is not yet functional.
   $task_class = "Drupal\\Core\\Database\\Driver\\{$driver}\\Install\\Tasks";
-  return new $task_class();
+  return new $task_class($database);
 }
diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
index 02c9dd2..06f03f7 100644
--- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
+++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php
@@ -55,14 +55,6 @@
   const CACHE_PERMANENT = 0;
 
   /**
-   * Constructs a new cache backend.
-   *
-   * @param $bin
-   *   The cache bin for which the object is created.
-   */
-  function __construct($bin);
-
-  /**
    * Returns data from the persistent cache.
    *
    * Data may be stored as either plain text or as serialized data. cache_get()
diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php
deleted file mode 100644
index da42a26..0000000
--- a/core/lib/Drupal/Core/Cache/CacheFactory.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\Core\Cache\CacheFactory.
- */
-
-namespace Drupal\Core\Cache;
-
-/**
- * Defines the cache backend factory.
- */
-class CacheFactory {
-
-  /**
-   * Instantiates a cache backend class for a given cache bin.
-   *
-   * By default, this returns an instance of the
-   * Drupal\Core\Cache\DatabaseBackend class.
-   *
-   * Classes implementing Drupal\Core\Cache\CacheBackendInterface can register
-   * themselves both as a default implementation and for specific bins.
-   *
-   * @param string $bin
-   *   The cache bin for which a cache backend object should be returned.
-   *
-   * @return Drupal\Core\Cache\CacheBackendInterface
-   *   The cache backend object associated with the specified bin.
-   */
-  public static function get($bin) {
-    // Check whether there is a custom class defined for the requested bin or
-    // use the default 'cache' definition otherwise.
-    $cache_backends = self::getBackends();
-    $class = isset($cache_backends[$bin]) ? $cache_backends[$bin] : $cache_backends['cache'];
-    return new $class($bin);
-  }
-
-  /**
-   * Returns a list of cache backends for this site.
-   *
-   * @return array
-   *   An associative array with cache bins as keys, and backend class names as
-   *   value.
-   */
-  public static function getBackends() {
-    // @todo Improve how cache backend classes are defined. Cannot be
-    //   configuration, since e.g. the CachedStorage config storage controller
-    //   requires the definition in its constructor already.
-    global $conf;
-    $cache_backends = isset($conf['cache_classes']) ? $conf['cache_classes'] : array();
-    // Ensure there is a default 'cache' bin definition.
-    $cache_backends += array('cache' => 'Drupal\Core\Cache\DatabaseBackend');
-    return $cache_backends;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index e62f1da..3aea56f 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Cache;
 
-use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
 use Exception;
 
 /**
@@ -24,16 +24,25 @@ class DatabaseBackend implements CacheBackendInterface {
   protected $bin;
 
   /**
+   * A database connection object.
+   */
+  protected $dbConnection;
+
+  /**
    * A static cache of all tags checked during the request.
    */
   protected static $tagCache = array();
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::__construct().
+   * Constructs a new cache database backend.
+   *
+   * @param string $bin
+   *   (optional) The cache bin that should be used.
+   * @param Drupal\Core\Database\Connection $connection
+   *   The database connection that should be used.
    */
-  function __construct($bin) {
-    // All cache tables should be prefixed with 'cache_', except for the
-    // default 'cache' bin.
+ function __construct($bin, Connection $connection) {
+    $this->dbConnection = $connection;
     if ($bin != 'cache') {
       $bin = 'cache_' . $bin;
     }
@@ -61,7 +70,7 @@ function getMultiple(&$cids) {
       // is used here only due to the performance overhead we would incur
       // otherwise. When serving an uncached page, the overhead of using
       // ::select() is a much smaller proportion of the request.
-      $result = Database::getConnection()->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . Database::getConnection()->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
+      $result = $this->dbConnection->query('SELECT cid, data, created, expire, serialized, tags, checksum FROM {' . $this->dbConnection->escapeTable($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
       $cache = array();
       foreach ($result as $item) {
         $item = $this->prepareItem($item);
@@ -136,7 +145,7 @@ function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, arra
     }
 
     try {
-      Database::getConnection()->merge($this->bin)
+      $this->dbConnection->merge($this->bin)
         ->key(array('cid' => $cid))
         ->fields($fields)
         ->execute();
@@ -150,7 +159,7 @@ function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, arra
    * Implements Drupal\Core\Cache\CacheBackendInterface::delete().
    */
   function delete($cid) {
-    Database::getConnection()->delete($this->bin)
+    $this->dbConnection->delete($this->bin)
       ->condition('cid', $cid)
       ->execute();
   }
@@ -161,7 +170,7 @@ function delete($cid) {
   function deleteMultiple(array $cids) {
     // Delete in chunks when a large array is passed.
     do {
-      Database::getConnection()->delete($this->bin)
+      $this->dbConnection->delete($this->bin)
         ->condition('cid', array_splice($cids, 0, 1000), 'IN')
         ->execute();
     }
@@ -172,14 +181,14 @@ function deleteMultiple(array $cids) {
    * Implements Drupal\Core\Cache\CacheBackendInterface::flush().
    */
   function flush() {
-    Database::getConnection()->truncate($this->bin)->execute();
+    $this->dbConnection->truncate($this->bin)->execute();
   }
 
   /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::expire().
    */
   function expire() {
-    Database::getConnection()->delete($this->bin)
+    $this->dbConnection->delete($this->bin)
       ->condition('expire', CacheBackendInterface::CACHE_PERMANENT, '<>')
       ->condition('expire', REQUEST_TIME, '<')
       ->execute();
@@ -242,7 +251,7 @@ protected function flattenTags(array $tags) {
   public function invalidateTags(array $tags) {
     foreach ($this->flattenTags($tags) as $tag) {
       unset(self::$tagCache[$tag]);
-      Database::getConnection()->merge('cache_tags')
+      $this->dbConnection->merge('cache_tags')
         ->key(array('tag' => $tag))
         ->fields(array('invalidations' => 1))
         ->expression('invalidations', 'invalidations + 1')
@@ -273,7 +282,7 @@ protected function checksumTags($tags) {
    }
     if ($query_tags) {
       try {
-        if ($db_tags = Database::getConnection()->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) {
+        if ($db_tags = $this->dbConnection->query('SELECT tag, invalidations FROM {cache_tags} WHERE tag IN (:tags)', array(':tags' => $query_tags))->fetchAllKeyed()) {
           self::$tagCache = array_merge(self::$tagCache, $db_tags);
           $checksum += array_sum($db_tags);
         }
@@ -290,7 +299,7 @@ protected function checksumTags($tags) {
    */
   function isEmpty() {
     $this->garbageCollection();
-    $query = Database::getConnection()->select($this->bin);
+    $query = $this->dbConnection->select($this->bin);
     $query->addExpression('1');
     $result = $query->range(0, 1)
       ->execute()
diff --git a/core/lib/Drupal/Core/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php
index 73aae39..1006c93 100644
--- a/core/lib/Drupal/Core/Cache/InstallBackend.php
+++ b/core/lib/Drupal/Core/Cache/InstallBackend.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Cache;
 
+use Drupal\Core\Database\Database;
 use Exception;
 
 /**
@@ -34,6 +35,22 @@
 class InstallBackend extends DatabaseBackend {
 
   /**
+   * Constructs an Drupal\Core\Cache\InstallBackend object.
+   *
+   * @param string $bin
+   *   (optional) The cache bin that should be used.
+   */
+  function __construct($bin) {
+    if (class_exists('Drupal\Core\Database\Database') && drupal_container()->hasParameter('database.info')) {
+      $this->dbConnection = Database::getConnection('default', NULL, drupal_container()->getParameter('database.info'));
+    }
+    if ($bin != 'cache') {
+      $bin = 'cache_' . $bin;
+    }
+    $this->bin = $bin;
+  }
+
+  /**
    * Overrides Drupal\Core\Cache\DatabaseBackend::get().
    */
   function get($cid) {
diff --git a/core/lib/Drupal/Core/Cache/MemoryBackend.php b/core/lib/Drupal/Core/Cache/MemoryBackend.php
index ce74c2f..5b618d3 100644
--- a/core/lib/Drupal/Core/Cache/MemoryBackend.php
+++ b/core/lib/Drupal/Core/Cache/MemoryBackend.php
@@ -29,12 +29,6 @@ class MemoryBackend implements CacheBackendInterface {
   protected $invalidatedTags = array();
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::__construct().
-   */
-  public function __construct($bin) {
-  }
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
   public function get($cid) {
diff --git a/core/lib/Drupal/Core/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php
index 862a3bd..5ad4ac1 100644
--- a/core/lib/Drupal/Core/Cache/NullBackend.php
+++ b/core/lib/Drupal/Core/Cache/NullBackend.php
@@ -21,11 +21,6 @@
 class NullBackend implements CacheBackendInterface {
 
   /**
-   * Implements Drupal\Core\Cache\CacheBackendInterface::__construct().
-   */
-  function __construct($bin) {}
-
-  /**
    * Implements Drupal\Core\Cache\CacheBackendInterface::get().
    */
   function get($cid) {
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index ed15dd5..25cbb63 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -46,14 +46,17 @@ public function build(ContainerBuilder $container) {
     $container->register('language_manager', 'Drupal\Core\Language\LanguageManager')
       ->addArgument(new Reference('request'))
       ->setScope('request');
-    $container->register('database', 'Drupal\Core\Database\Connection')
-      ->setFactoryClass('Drupal\Core\Database\Database')
-      ->setFactoryMethod('getConnection')
-      ->addArgument('default');
-    $container->register('database.slave', 'Drupal\Core\Database\Connection')
-      ->setFactoryClass('Drupal\Core\Database\Database')
-      ->setFactoryMethod('getConnection')
-      ->addArgument('slave');
+
+    foreach (array('block', 'field', 'filter', 'form', 'page', 'menu', 'path', 'test') as $bin) {
+      $id = 'cache.' . $bin;
+      // Only define the bin if it has not yet been defined.
+      if (!$container->has($id)) {
+        $definition = clone $container->getDefinition('cache');
+        // Each backend must define the bin as it's first constructor argument.
+        $container->setDefinition($id, $definition->replaceArgument(0, $bin));
+      }
+    }
+
     $container->register('typed_data', 'Drupal\Core\TypedData\TypedDataManager');
     // Add the user's storage for temporary, non-cache data.
     $container->register('lock', 'Drupal\Core\Lock\DatabaseLockBackend');
diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
index 6a425de..ac4c485 100644
--- a/core/lib/Drupal/Core/Database/Database.php
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -144,15 +144,20 @@
   /**
    * Gets the connection object for the specified database key and target.
    *
-   * @param $target
+   * @param string $target
    *   The database target name.
    * @param $key
    *   The database connection key. Defaults to NULL which means the active key.
+   * @param array $database_info
    *
    * @return Drupal\Core\Database\Connection
    *   The corresponding connection object.
    */
-  final public static function getConnection($target = 'default', $key = NULL) {
+  final public static function getConnection($target = 'default', $key = NULL, $database_info = array()) {
+    if (empty(self::$databaseInfo)) {
+      self::parseConnectionInfo($database_info);
+    }
+
     if (!isset($key)) {
       // By default, we want the active connection, set in setActiveConnection.
       $key = self::$activeKey;
@@ -195,7 +200,7 @@
    */
   final public static function setActiveConnection($key = 'default') {
     if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
+      throw new \LogicException('Database::setActiveConnection is called without specifying the database information first.');
     }
 
     if (!empty(self::$databaseInfo[$key])) {
@@ -208,10 +213,7 @@
   /**
    * Process the configuration file for database information.
    */
-  final public static function parseConnectionInfo() {
-    global $databases;
-
-    $database_info = is_array($databases) ? $databases : array();
+  final public static function parseConnectionInfo($database_info) {
     foreach ($database_info as $index => $info) {
       foreach ($database_info[$index] as $target => $value) {
         // If there is no "driver" property, then we assume it's an array of
@@ -287,7 +289,7 @@ public static function addConnectionInfo($key, $target, $info) {
    */
   final public static function getConnectionInfo($key = 'default') {
     if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
+      throw new \LogicException('Database::getConnectionInfo called without specifying the database information first.');
     }
 
     if (!empty(self::$databaseInfo[$key])) {
@@ -307,7 +309,7 @@ public static function addConnectionInfo($key, $target, $info) {
    */
   final public static function renameConnection($old_key, $new_key) {
     if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
+      throw new \LogicException('Database::renameConnection called without specifying the database information first.');
     }
 
     if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) {
@@ -359,9 +361,9 @@ public static function addConnectionInfo($key, $target, $info) {
    * @throws Drupal\Core\Database\ConnectionNotDefinedException
    * @throws Drupal\Core\Database\DriverNotSpecifiedException
    */
-  final protected static function openConnection($key, $target) {
+  final protected static function openConnection($key, $target, $database_info = array()) {
     if (empty(self::$databaseInfo)) {
-      self::parseConnectionInfo();
+      self::parseConnectionInfo($database_info);
     }
 
     // If the requested database does not exist then it is an unrecoverable
diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php
index 5d34a62..42eec41 100644
--- a/core/lib/Drupal/Core/Database/Install/Tasks.php
+++ b/core/lib/Drupal/Core/Database/Install/Tasks.php
@@ -19,6 +19,14 @@
  */
 abstract class Tasks {
 
+  protected $databases = array();
+
+  function __construct($database_info = NULL) {
+    if ($database_info) {
+      $this->databases['default']['default'] = $database_info;
+    }
+  }
+
   /**
    * Structure that describes each task to run.
    *
@@ -160,10 +168,7 @@ public function runTasks() {
    */
   protected function connect() {
     try {
-      // This doesn't actually test the connection.
-      db_set_active();
-      // Now actually do a check.
-      Database::getConnection();
+      Database::getConnection('default', NULL, $this->databases);
       $this->pass('Drupal can CONNECT to the database ok.');
     }
     catch (Exception $e) {
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index c61015b..30cd8a9 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -709,13 +709,13 @@ protected function changeDatabasePrefix() {
     }
     Database::addConnectionInfo('default', 'default', $connection_info['default']);
 
-    // Additionally override global $databases, since the installer does not use
+    // Additionally set database.info, since the installer does not use
     // the Database connection info.
     // @see install_verify_database_settings()
     // @see install_database_errors()
     // @todo Fix installer to use Database connection info.
-    global $databases;
     $databases['default']['default'] = $connection_info['default'];
+    drupal_container()->setParameter('database.info', $databases);
 
     // Indicate the database prefix was set up correctly.
     $this->setupDatabasePrefix = TRUE;
@@ -869,6 +869,9 @@ protected function tearDown() {
     // Reset all static variables.
     drupal_static_reset();
 
+    // Restore the original container.
+    drupal_container($this->originalContainer);
+
     // Reset module list and module load status.
     module_list_reset();
     module_load_all(FALSE, TRUE);
@@ -877,7 +880,6 @@ protected function tearDown() {
     $conf = $this->originalConf;
 
     // Restore original statics and globals.
-    drupal_container($this->originalContainer);
     $language_interface = $this->originalLanguage;
     $GLOBALS['config_directories'] = $this->originalConfigDirectories;
     if (isset($this->originalPrefix)) {
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 24bf1f2..9c8e9c4 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -613,6 +613,8 @@ protected function setUp() {
     // Reset all statics and variables to perform tests in a clean environment.
     $conf = array();
     drupal_static_reset();
+    // drupal_container() does not use drupal_static().
+    drupal_container(NULL, TRUE);
 
     // Change the database prefix.
     // All static variables need to be reset before the database prefix is
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php
index 585a3ff..97c82ec 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Cache;
 
 use Drupal\Core\Cache\DatabaseBackend;
+use Drupal\Core\Database\Database;
 
 /**
  * Tests DatabaseBackend using GenericCacheBackendUnitTestBase.
@@ -23,7 +24,7 @@ public static function getInfo() {
   }
 
   protected function createCacheBackend($bin) {
-    return new DatabaseBackend($bin);
+    return new DatabaseBackend(Database::getConnection(), $bin);
   }
 
   public function setUpCacheBackend() {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
index 58078cd..39e951b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/InstallTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Cache\DatabaseBackend;
 use Drupal\Core\Cache\InstallBackend;
+use Drupal\Core\Database\Database;
 use Exception;
 
 /**
@@ -49,7 +50,7 @@ public static function getInfo() {
    * clearing various items in the cache.
    */
   function testCacheInstall() {
-    $database_cache = new DatabaseBackend('test');
+    $database_cache = new DatabaseBackend(Database::getConnection(), 'test');
     $install_cache = new InstallBackend('test');
 
     // Store an item in the database cache, and confirm that the installer's
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index e138f32..0a4e09e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -184,7 +184,7 @@ function system_requirements($phase) {
   else {
     // Database information.
     $class = Database::getConnection()->getDriverClass('Install\\Tasks');
-    $tasks = new $class();
+    $tasks = new $class(drupal_container()->getParameter('database.info'));
     $requirements['database_system'] = array(
       'title' => $t('Database system'),
       'value' => $tasks->name(),
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 2395a84..40f4647 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -4,6 +4,8 @@
  * This script runs Drupal tests from command line.
  */
 
+use Drupal\Core\DrupalKernel;
+
 const SIMPLETEST_SCRIPT_COLOR_PASS = 32; // Green.
 const SIMPLETEST_SCRIPT_COLOR_FAIL = 31; // Red.
 const SIMPLETEST_SCRIPT_COLOR_EXCEPTION = 33; // Brown.
@@ -371,6 +373,10 @@ function simpletest_script_run_one_test($test_id, $test_class) {
     // Bootstrap Drupal.
     drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 
+    // Initialize and boot the kernel to get a fully loaded container.
+    $kernel = new DrupalKernel('prod', FALSE);
+    $kernel->boot();
+
     simpletest_classloader_register();
 
     // Override configuration according to command line parameters.
diff --git a/core/update.php b/core/update.php
index 2273b40..4ead949 100644
--- a/core/update.php
+++ b/core/update.php
@@ -268,7 +268,13 @@ function update_info_page() {
   _drupal_flush_css_js();
   // Flush the cache of all data for the update status module.
   if (db_table_exists('cache_update')) {
-    cache('update')->flush();
+    $query = db_delete('cache_update');
+    $query->condition(
+      db_or()
+      ->condition('cid', 'update_project_%', 'LIKE')
+      ->condition('cid', 'available_releases::%', 'LIKE')
+    );
+    $query->execute();
   }
 
   update_task_list('info');
