diff --git a/features.services.yml b/features.services.yml
index a4711b5..7f3b0f3 100644
--- a/features.services.yml
+++ b/features.services.yml
@@ -30,3 +30,10 @@ services:
   features.extension_optional_storage:
     class: Drupal\features\FeaturesInstallStorage
     arguments: ['@config.storage', 'config/optional']
+
+  features.config.installer:
+    class: Drupal\features\FeaturesConfigInstaller
+    public: false
+    decorates: config.installer
+    decoration_priority: 5
+    arguments: ['@features.config.installer.inner', '@features.manager', '@config.factory', '@config.manager', '@config.storage']
diff --git a/src/FeaturesConfigInstaller.php b/src/FeaturesConfigInstaller.php
index 04b04b1..cd9e7e0 100644
--- a/src/FeaturesConfigInstaller.php
+++ b/src/FeaturesConfigInstaller.php
@@ -7,8 +7,14 @@
 
 namespace Drupal\features;
 
-use Drupal\Core\Config\ConfigInstaller;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\ConfigInstallerInterface;
+use Drupal\Core\Config\FileStorage;
+use Drupal\Core\Config\InstallStorage;
+use Drupal\Core\Config\ConfigManagerInterface;
 use Drupal\Core\Config\StorageInterface;
+use Drupal\Core\Site\Settings;
+use Drupal\features\FeaturesManagerInterface;
 
 /**
  * Class for customizing the test for pre existing configuration.
@@ -16,7 +22,369 @@ use Drupal\Core\Config\StorageInterface;
  * Copy of ConfigInstaller with findPreExistingConfiguration() modified to
  * allow Feature modules to be installed.
  */
-class FeaturesConfigInstaller extends ConfigInstaller {
+class FeaturesConfigInstaller implements ConfigInstallerInterface {
+
+  /**
+   * The configuration installer.
+   *
+   * @var \Drupal\Core\Config\ConfigInstallerInterface
+   */
+  protected $configInstaller;
+
+  /**
+   * The features manager.
+   *
+   * @var \Drupal\features\FeaturesManagerInterface
+   */
+  protected $featuresManager;
+
+  /**
+   * The configuration factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The configuration manager.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface
+   */
+  protected $configManager;
+
+  /**
+   * The active configuration storages, keyed by collection.
+   *
+   * @var \Drupal\Core\Config\StorageInterface[]
+   */
+  protected $activeStorages;
+
+  /**
+   * Constructs a new FeaturesConfigInstaller object.
+   *
+   * @param \Drupal\Core\Config\ConfigInstallerInterface $config_installer
+   *    The configuration installer.
+   * @param \Drupal\features\FeaturesManagerInterface $features_manager
+   *    The features manager.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The configuration factory.
+   * @param \Drupal\Core\Config\ConfigManagerInterface $config_manager
+   *   The configuration manager.
+   * @param \Drupal\Core\Config\StorageInterface $active_storage
+   *   The active configuration storage.
+   */
+  public function __construct(ConfigInstallerInterface $config_installer, FeaturesManagerInterface $features_manager, ConfigFactoryInterface $config_factory, ConfigManagerInterface $config_manager, StorageInterface $active_storage) {
+    $this->configInstaller = $config_installer;
+    $this->featuresManager = $features_manager;
+    $this->configFactory = $config_factory;
+    $this->configManager = $config_manager;
+    $this->activeStorages[$active_storage->getCollectionName()] = $active_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function installDefaultConfig($type, $name) {
+    return $this->configInstaller->installDefaultConfig($type, $name);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function installOptionalConfig(StorageInterface $storage = NULL, $dependency = []) {
+    return $this->configInstaller->installOptionalConfig($storage, $dependency);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function installCollectionDefaultConfig($collection) {
+    return $this->configInstaller->installCollectionDefaultConfig($collection);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setSourceStorage(StorageInterface $storage) {
+    return $this->configInstaller->setSourceStorage($storage);
+  }
+
+  /**
+   * Gets the configuration storage that provides the active configuration.
+   *
+   * @param string $collection
+   *   (optional) The configuration collection. Defaults to the default
+   *   collection.
+   *
+   * @return \Drupal\Core\Config\StorageInterface
+   *   The configuration storage that provides the default configuration.
+   */
+  protected function getActiveStorages($collection = StorageInterface::DEFAULT_COLLECTION) {
+    if (!isset($this->activeStorages[$collection])) {
+      $this->activeStorages[$collection] = reset($this->activeStorages)->createCollection($collection);
+    }
+    return $this->activeStorages[$collection];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setSyncing($status) {
+    return $this->configInstaller->setSyncing($status);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isSyncing() {
+    return $this->configInstaller->isSyncing();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkConfigurationToInstall($type, $name) {
+    if ($this->isSyncing()) {
+      // Configuration is assumed to already be checked by the config importer
+      // validation events.
+      return;
+    }
+    $config_install_path = $this->getDefaultConfigDirectory($type, $name);
+    if (!is_dir($config_install_path)) {
+      return;
+    }
+
+    $storage = new FileStorage($config_install_path, StorageInterface::DEFAULT_COLLECTION);
+
+    $enabled_extensions = $this->getEnabledExtensions();
+    // Add the extension that will be enabled to the list of enabled extensions.
+    $enabled_extensions[] = $name;
+    // Gets profile storages to search for overrides if necessary.
+    $profile_storages = $this->getProfileStorages($name);
+
+    // Check the dependencies of configuration provided by the module.
+    $invalid_default_config = $this->findDefaultConfigWithUnmetDependencies($storage, $enabled_extensions, $profile_storages);
+    if (!empty($invalid_default_config)) {
+      throw UnmetDependenciesException::create($name, $invalid_default_config);
+    }
+
+    // Install profiles can not have config clashes. Configuration that
+    // has the same name as a module's configuration will be used instead.
+    if ($name != $this->drupalGetProfile()) {
+      // Throw an exception if the module being installed contains configuration
+      // that already exists. Additionally, can not continue installing more
+      // modules because those may depend on the current module being installed.
+      $existing_configuration = $this->findPreExistingConfiguration($storage);
+      if (!empty($existing_configuration)) {
+        throw PreExistingConfigException::create($name, $existing_configuration);
+      }
+    }
+  }
+
+  /**
+   * Gets configuration data from the provided storage to create.
+   *
+   * @param StorageInterface $storage
+   *   The configuration storage to read configuration from.
+   * @param string $collection
+   *  The configuration collection to use.
+   * @param string $prefix
+   *   (optional) Limit to configuration starting with the provided string.
+   * @param \Drupal\Core\Config\StorageInterface[] $profile_storages
+   *   An array of storage interfaces containing profile configuration to check
+   *   for overrides.
+   *
+   * @return array
+   *   An array of configuration data read from the source storage keyed by the
+   *   configuration object name.
+   */
+  protected function getConfigToCreate(StorageInterface $storage, $collection, $prefix = '', array $profile_storages = []) {
+    if ($storage->getCollectionName() != $collection) {
+      $storage = $storage->createCollection($collection);
+    }
+    $data = $storage->readMultiple($storage->listAll($prefix));
+
+    // Check to see if the corresponding override storage has any overrides.
+    foreach ($profile_storages as $profile_storage) {
+      if ($profile_storage->getCollectionName() != $collection) {
+        $profile_storage = $profile_storage->createCollection($collection);
+      }
+      $data = $profile_storage->readMultiple(array_keys($data)) + $data;
+    }
+    return $data;
+  }
+
+  /**
+   * Finds default configuration with unmet dependencies.
+   *
+   * @param \Drupal\Core\Config\StorageInterface $storage
+   *   The storage containing the default configuration.
+   * @param array $enabled_extensions
+   *   A list of all the currently enabled modules and themes.
+   * @param \Drupal\Core\Config\StorageInterface[] $profile_storages
+   *   An array of storage interfaces containing profile configuration to check
+   *   for overrides.
+   *
+   * @return array
+   *   List of configuration that has unmet dependencies
+   */
+  protected function findDefaultConfigWithUnmetDependencies(StorageInterface $storage, array $enabled_extensions, array $profile_storages = []) {
+    $config_to_create = $this->getConfigToCreate($storage, StorageInterface::DEFAULT_COLLECTION, '', $profile_storages);
+    $all_config = array_merge($this->configFactory->listAll(), array_keys($config_to_create));
+    return array_filter(array_keys($config_to_create), function($config_name) use ($enabled_extensions, $all_config, $config_to_create) {
+      return !$this->validateDependencies($config_name, $config_to_create[$config_name], $enabled_extensions, $all_config);
+    });
+  }
+
+  /**
+   * Validates an array of config data that contains dependency information.
+   *
+   * @param string $config_name
+   *   The name of the configuration object that is being validated.
+   * @param array $data
+   *   Configuration data.
+   * @param array $enabled_extensions
+   *   A list of all the currently enabled modules and themes.
+   * @param array $all_config
+   *   A list of all the active configuration names.
+   *
+   * @return bool
+   *   TRUE if the dependencies are met, FALSE if not.
+   */
+  protected function validateDependencies($config_name, array $data, array $enabled_extensions, array $all_config) {
+    if (isset($data['dependencies'])) {
+      $all_dependencies = $data['dependencies'];
+
+      // Ensure enforced dependencies are included.
+      if (isset($all_dependencies['enforced'])) {
+        $all_dependencies = array_merge($all_dependencies, $data['dependencies']['enforced']);
+        unset($all_dependencies['enforced']);
+      }
+      // Ensure the configuration entity type provider is in the list of
+      // dependencies.
+      list($provider) = explode('.', $config_name, 2);
+      if (!isset($all_dependencies['module'])) {
+        $all_dependencies['module'][] = $provider;
+      }
+      elseif (!in_array($provider, $all_dependencies['module'])) {
+        $all_dependencies['module'][] = $provider;
+      }
+
+      foreach ($all_dependencies as $type => $dependencies) {
+        $list_to_check = [];
+        switch ($type) {
+          case 'module':
+          case 'theme':
+            $list_to_check = $enabled_extensions;
+            break;
+          case 'config':
+            $list_to_check = $all_config;
+            break;
+        }
+        if (!empty($list_to_check)) {
+          $missing = array_diff($dependencies, $list_to_check);
+          if (!empty($missing)) {
+            return FALSE;
+          }
+        }
+      }
+    }
+    return TRUE;
+  }
+
+  /**
+   * Gets the list of enabled extensions including both modules and themes.
+   *
+   * @return array
+   *   A list of enabled extensions which includes both modules and themes.
+   */
+  protected function getEnabledExtensions() {
+    // Read enabled extensions directly from configuration to avoid circular
+    // dependencies on ModuleHandler and ThemeHandler.
+    $extension_config = $this->configFactory->get('core.extension');
+    $enabled_extensions = (array) $extension_config->get('module');
+    $enabled_extensions += (array) $extension_config->get('theme');
+    // Core can provide configuration.
+    $enabled_extensions['core'] = 'core';
+    return array_keys($enabled_extensions);
+  }
+
+  /**
+   * Gets the profile storage to use to check for profile overrides.
+   *
+   * The install profile can override module configuration during a module
+   * install. Both the install and optional directories are checked for matching
+   * configuration. This allows profiles to override default configuration for
+   * modules they do not depend on.
+   *
+   * @param string $installing_name
+   *   (optional) The name of the extension currently being installed.
+   *
+   * @return \Drupal\Core\Config\StorageInterface[]|null
+   *   Storages to access configuration from the installation profile. If we're
+   *   installing the profile itself, then it will return an empty array as the
+   *   profile storage should not be used.
+   */
+  protected function getProfileStorages($installing_name = '') {
+    $profile = $this->drupalGetProfile();
+    $profile_storages = [];
+    if ($profile && $profile != $installing_name) {
+      $profile_path = $this->drupalGetPath('module', $profile);
+      foreach ([InstallStorage::CONFIG_INSTALL_DIRECTORY, InstallStorage::CONFIG_OPTIONAL_DIRECTORY] as $directory) {
+        if (is_dir($profile_path . '/' . $directory)) {
+          $profile_storages[] = new FileStorage($profile_path . '/' . $directory, StorageInterface::DEFAULT_COLLECTION);
+        }
+      }
+    }
+    return $profile_storages;
+  }
+
+  /**
+   * Gets an extension's default configuration directory.
+   *
+   * @param string $type
+   *   Type of extension to install.
+   * @param string $name
+   *   Name of extension to install.
+   *
+   * @return string
+   *   The extension's default configuration directory.
+   */
+  protected function getDefaultConfigDirectory($type, $name) {
+    return $this->drupalGetPath($type, $name) . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
+  }
+
+  /**
+   * Wrapper for drupal_get_path().
+   *
+   * @param $type
+   *   The type of the item; one of 'core', 'profile', 'module', 'theme', or
+   *   'theme_engine'.
+   * @param $name
+   *   The name of the item for which the path is requested. Ignored for
+   *   $type 'core'.
+   *
+   * @return string
+   *   The path to the requested item or an empty string if the item is not
+   *   found.
+   */
+  protected function drupalGetPath($type, $name) {
+    return drupal_get_path($type, $name);
+  }
+
+  /**
+   * Gets the install profile from settings.
+   *
+   * @return string|null $profile
+   *   The name of the installation profile or NULL if no installation profile
+   *   is currently active. This is the case for example during the first steps
+   *   of the installer or during unit tests.
+   */
+  protected function drupalGetProfile() {
+    // Settings is safe to use because settings.php is written before any module
+    // is installed.
+    return Settings::get('install_profile');
+  }
 
   /**
    * {@inheritdoc}
@@ -27,7 +395,7 @@ class FeaturesConfigInstaller extends ConfigInstaller {
     // Drupal\Core\Config\ConfigInstaller::findPreExistingConfiguration().
     // Allow config that already exists coming from Features.
     /** @var \Drupal\features\FeaturesManagerInterface $manager */
-    $manager = \Drupal::service('features.manager');
+    $manager = $this->featuresManager;
     $features_config = array_keys($manager->listExistingConfig());
     // Map array so we can use isset instead of in_array for faster access.
     $features_config = array_combine($features_config, $features_config);
diff --git a/src/FeaturesServiceProvider.php b/src/FeaturesServiceProvider.php
deleted file mode 100644
index 6075275..0000000
--- a/src/FeaturesServiceProvider.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\features\FeaturesServiceProvider.
- */
-
-namespace Drupal\features;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceProviderBase;
-
-/**
- * Service provider implementation for Features to override config.installer.
- *
- * @ingroup container
- */
-class FeaturesServiceProvider extends ServiceProviderBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    // Override the config.installer class with a new class.
-    $definition = $container->getDefinition('config.installer');
-    $definition->setClass('Drupal\features\FeaturesConfigInstaller');
-  }
-
-}
