diff --git a/core/core.services.yml b/core/core.services.yml
index 951c458..3bd4625 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -800,7 +800,15 @@ services:
     class: Drupal\Core\Asset\AssetDumper
   library.discovery:
     class: Drupal\Core\Asset\LibraryDiscovery
-    arguments: ['@cache.discovery', '@module_handler']
+    arguments: ['@library.discovery.collector']
+  library.discovery.parser:
+    class: Drupal\Core\Asset\LibraryDiscoveryParser
+    arguments: ['@module_handler']
+  library.discovery.collector:
+    class: Drupal\Core\Asset\LibraryDiscoveryCollector
+    arguments: ['@cache.discovery', '@lock', '@library.discovery.parser']
+    tags:
+      - { name: needs_destruction }
   info_parser:
     class: Drupal\Core\Extension\InfoParser
   element_info:
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
index 2a25ea3..b0c3696 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
@@ -7,14 +7,7 @@
 
 namespace Drupal\Core\Asset;
 
-use Drupal\Component\Serialization\Yaml;
-use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
-use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
-use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Core\Cache\CacheCollectorInterface;
 
 /**
  * Discovers available asset libraries in Drupal.
@@ -22,25 +15,11 @@
 class LibraryDiscovery implements LibraryDiscoveryInterface {
 
   /**
-   * Stores the library information keyed by extension.
+   * The library discovery cache collector.
    *
-   * @var array
+   * @var \Drupal\Core\Cache\CacheCollectorInterface
    */
-  protected $libraries;
-
-  /**
-   * The cache backend.
-   *
-   * @var \Drupal\Core\Cache\CacheBackendInterface
-   */
-  protected $cache;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
+  protected $collector;
 
   /**
    * Constructs a new LibraryDiscovery instance.
@@ -50,263 +29,23 @@ class LibraryDiscovery implements LibraryDiscoveryInterface {
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    */
-  public function __construct(CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    $this->cache = $cache_backend;
-    $this->moduleHandler = $module_handler;
+  public function __construct(CacheCollectorInterface $library_discovery_collector) {
+    $this->collector = $library_discovery_collector;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getLibrariesByExtension($extension) {
-    $this->ensureLibraryInformation($extension);
-    return $this->libraries[$extension];
+    return $this->collector->get($extension);
   }
 
   /**
    * {@inheritdoc}
    */
   public function getLibraryByName($extension, $name) {
-    $this->ensureLibraryInformation($extension);
-    return isset($this->libraries[$extension][$name]) ? $this->libraries[$extension][$name] : FALSE;
-  }
-
-  /**
-   * Ensures that the libraries property is filled.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function ensureLibraryInformation($extension) {
-    $this->getCache($extension);
-    if (!isset($this->libraries[$extension])) {
-      if ($information = $this->buildLibrariesByExtension($extension)) {
-        $this->libraries[$extension] = $information;
-      }
-      else {
-        $this->libraries[$extension] = FALSE;
-      }
-      $this->setCache($extension, $this->libraries[$extension]);
-    }
-  }
-
-  /**
-   * Fills up the libraries property from cache, if available.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function getCache($extension) {
-    if (!isset($this->libraries[$extension])) {
-      if ($cache = $this->cache->get('library:info:' . $extension)) {
-        $this->libraries[$extension] = $cache->data;
-      }
-    }
-  }
-
-  /**
-   * Sets the library information into a cache entry.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   *
-   * @param bool|array $information
-   *   All library definitions of the passed extension or FALSE if no
-   *   information is available.
-   */
-  protected function setCache($extension, $information) {
-    $this->cache->set('library:info:' . $extension, $information, Cache::PERMANENT, array(
-      'extension' => array(TRUE, $extension),
-      'library_info' => array(TRUE),
-    ));
-  }
-
-  /**
-   * Parses and builds up all the libraries information of an extension.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   *
-   * @return array
-   *   All library definitions of the passed extension.
-   *
-   * @throws \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException
-   *   Thrown when a library has no js/css/setting.
-   * @throws \UnexpectedValueException
-   *   Thrown when a js file defines a positive weight.
-   */
-  protected function buildLibrariesByExtension($extension) {
-    $this->libraries[$extension] = array();
-    if ($extension === 'core') {
-      $path = 'core';
-      $extension_type = 'core';
-    }
-    else {
-      if ($this->moduleHandler->moduleExists($extension)) {
-        $extension_type = 'module';
-      }
-      else {
-        $extension_type = 'theme';
-      }
-      $path = $this->drupalGetPath($extension_type, $extension);
-    }
-    $library_file = $path . '/' . $extension . '.libraries.yml';
-
-    if ($library_file && file_exists(DRUPAL_ROOT . '/' . $library_file)) {
-      $this->libraries[$extension] = array();
-      $this->parseLibraryInfo($extension, $library_file);
-    }
-
-    foreach ($this->libraries[$extension] as $id => &$library) {
-      if (!isset($library['js']) && !isset($library['css']) && !isset($library['settings'])) {
-        throw new IncompleteLibraryDefinitionException(sprintf("Incomplete library definition for '%s' in %s", $id, $library_file));
-      }
-      $library += array('dependencies' => array(), 'js' => array(), 'css' => array());
-
-      if (isset($library['version'])) {
-        // @todo Retrieve version of a non-core extension.
-        if ($library['version'] === 'VERSION') {
-          $library['version'] = \Drupal::VERSION;
-        }
-        // Remove 'v' prefix from external library versions.
-        elseif ($library['version'][0] === 'v') {
-          $library['version'] = substr($library['version'], 1);
-        }
-      }
-
-      foreach (array('js', 'css') as $type) {
-        // Prepare (flatten) the SMACSS-categorized definitions.
-        // @todo After Asset(ic) changes, retain the definitions as-is and
-        //   properly resolve dependencies for all (css) libraries per category,
-        //   and only once prior to rendering out an HTML page.
-        if ($type == 'css' && !empty($library[$type])) {
-          foreach ($library[$type] as $category => $files) {
-            foreach ($files as $source => $options) {
-              if (!isset($options['weight'])) {
-                $options['weight'] = 0;
-              }
-              // Apply the corresponding weight defined by CSS_* constants.
-              $options['weight'] += constant('CSS_' . strtoupper($category));
-              $library[$type][$source] = $options;
-            }
-            unset($library[$type][$category]);
-          }
-        }
-        foreach ($library[$type] as $source => $options) {
-          unset($library[$type][$source]);
-          // Allow to omit the options hashmap in YAML declarations.
-          if (!is_array($options)) {
-            $options = array();
-          }
-          if ($type == 'js' && isset($options['weight']) && $options['weight'] > 0) {
-            throw new \UnexpectedValueException("The $extension/$id library defines a positive weight for '$source'. Only negative weights are allowed (but should be avoided). Instead of a positive weight, specify accurate dependencies for this library.");
-          }
-          // Unconditionally apply default groups for the defined asset files.
-          // The library system is a dependency management system. Each library
-          // properly specifies its dependencies instead of relying on a custom
-          // processing order.
-          if ($type == 'js') {
-            $options['group'] = JS_LIBRARY;
-          }
-          elseif ($type == 'css') {
-            $options['group'] = $extension_type == 'theme' ? CSS_AGGREGATE_THEME : CSS_AGGREGATE_DEFAULT;
-          }
-          // By default, all library assets are files.
-          if (!isset($options['type'])) {
-            $options['type'] = 'file';
-          }
-          if ($options['type'] == 'external') {
-            $options['data'] = $source;
-          }
-          // Determine the file asset URI.
-          else {
-            if ($source[0] === '/') {
-              // An absolute path maps to DRUPAL_ROOT / base_path().
-              if ($source[1] !== '/') {
-                $options['data'] = substr($source, 1);
-              }
-              // A protocol-free URI (e.g., //cdn.com/example.js) is external.
-              else {
-                $options['type'] = 'external';
-                $options['data'] = $source;
-              }
-            }
-            // A stream wrapper URI (e.g., public://generated_js/example.js).
-            elseif ($this->fileValidUri($source)) {
-              $options['data'] = $source;
-            }
-            // By default, file paths are relative to the registering extension.
-            else {
-              $options['data'] = $path . '/' . $source;
-            }
-          }
-
-          if (!isset($library['version'])) {
-            // @todo Get the information from the extension.
-            $options['version'] = -1;
-          }
-          else {
-            $options['version'] = $library['version'];
-          }
-
-          $library[$type][] = $options;
-        }
-      }
-
-      // @todo Introduce drupal_add_settings().
-      if (isset($library['settings'])) {
-        $library['js'][] = array(
-          'type' => 'setting',
-          'data' => $library['settings'],
-        );
-        unset($library['settings']);
-      }
-      // @todo Convert all uses of #attached[library][]=array('provider','name')
-      //   into #attached[library][]='provider/name' and remove this.
-      foreach ($library['dependencies'] as $i => $dependency) {
-        $library['dependencies'][$i] = $dependency;
-      }
-    }
-    return $this->libraries[$extension];
-  }
-
-  /**
-   * Wraps drupal_get_path().
-   */
-  protected function drupalGetPath($type, $name) {
-    return drupal_get_path($type, $name);
-  }
-
-  /**
-   * Wraps file_valid_uri().
-   */
-  protected function fileValidUri($source) {
-    return file_valid_uri($source);
-  }
-
-  /**
-   * Parses a given library file and allows module to alter it.
-   *
-   * This method sets the parsed information onto the library property.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   * @param string $library_file
-   *   The relative filename to the DRUPAL_ROOT of the wanted library file.
-   *
-   * @throws \Drupal\Core\Asset\Exception\InvalidLibraryFileException
-   *   Thrown when a parser exception got thrown.
-   */
-  protected function parseLibraryInfo($extension, $library_file) {
-    try {
-      $this->libraries[$extension] = Yaml::decode(file_get_contents(DRUPAL_ROOT . '/' . $library_file));
-    }
-    catch (InvalidDataTypeException $e) {
-      // Rethrow a more helpful exception to provide context.
-      throw new InvalidLibraryFileException(sprintf('Invalid library definition in %s: %s', $library_file, $e->getMessage()), 0, $e);
-    }
-    // Allow modules to alter the module's registered libraries.
-    $this->moduleHandler->alter('library_info', $this->libraries[$extension], $extension);
+    $extension = $this->getLibrariesByExtension($extension);
+    return isset($extension[$name]) ? $extension[$name] : FALSE;
   }
 
 }
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
new file mode 100644
index 0000000..f30edac
--- /dev/null
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Asset\LibraryDiscoveryCollector.
+ */
+
+namespace Drupal\Core\Asset;
+
+use Drupal\Core\Cache\CacheCollector;
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Lock\LockBackendInterface;
+
+/**
+ * Class LibraryDiscoveryCollector.
+ */
+class LibraryDiscoveryCollector extends CacheCollector {
+
+  /**
+   * The cache key.
+   *
+   * @var string
+   */
+  protected $cacheKey = 'library_info';
+
+  /**
+   * The cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cache;
+
+  /**
+   * The lock backend.
+   *
+   * @var \Drupal\Core\Lock\LockBackendInterface
+   */
+  protected $lock;
+
+  /**
+   * The library discovery parser.
+   *
+   * @var \Drupal\Core\Asset\LibraryDiscoveryParser
+   */
+  protected $discoveryParser;
+
+  /**
+   * Constructs a CacheCollector object.
+   *
+   * @param string $cid
+   *   The cid for the array being cached.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
+   *   The cache backend.
+   * @param \Drupal\Core\Lock\LockBackendInterface $lock
+   *   The lock backend.
+   * @param \Drupal\Core\Asset\LibraryDiscoveryParser $discovery_parser
+   *   The library discovery parser.
+   */
+  public function __construct(CacheBackendInterface $cache, LockBackendInterface $lock, LibraryDiscoveryParser $discovery_parser) {
+    parent::__construct($this->cacheKey, $cache, $lock, array($this->cacheKey => array(TRUE)));
+
+    $this->discoveryParser = $discovery_parser;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function resolveCacheMiss($key) {
+    $this->storage[$key] = $this->discoveryParser->buildLibrariesByExtension($key);
+    $this->persist($key);
+
+    return $this->storage[$key];
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
similarity index 74%
copy from core/lib/Drupal/Core/Asset/LibraryDiscovery.php
copy to core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index 2a25ea3..808fe42 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -2,40 +2,30 @@
 
 /**
  * @file
- * Contains \Drupal\Core\Asset\LibraryDiscovery.
+ * Contains \Drupal\Core\Asset\LibraryDiscoveryParser.
  */
 
 namespace Drupal\Core\Asset;
 
-use Drupal\Component\Serialization\Yaml;
-use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
 use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
 use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
-use Drupal\Core\Cache\Cache;
-use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Extension\ThemeHandlerInterface;
+use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
+use Drupal\Component\Serialization\Yaml;
 
 /**
- * Discovers available asset libraries in Drupal.
+ * Parses library files to get extension data.
  */
-class LibraryDiscovery implements LibraryDiscoveryInterface {
+class LibraryDiscoveryParser {
 
   /**
-   * Stores the library information keyed by extension.
+   * An array of discovered library extensions.
    *
    * @var array
    */
   protected $libraries;
 
   /**
-   * The cache backend.
-   *
-   * @var \Drupal\Core\Cache\CacheBackendInterface
-   */
-  protected $cache;
-
-  /**
    * The module handler.
    *
    * @var \Drupal\Core\Extension\ModuleHandlerInterface
@@ -43,85 +33,14 @@ class LibraryDiscovery implements LibraryDiscoveryInterface {
   protected $moduleHandler;
 
   /**
-   * Constructs a new LibraryDiscovery instance.
-   *
-   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
-   *   The cache backend.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
+   *   The moduel handler.
    */
-  public function __construct(CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    $this->cache = $cache_backend;
+  public function __construct(ModuleHandlerInterface $module_handler) {
     $this->moduleHandler = $module_handler;
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function getLibrariesByExtension($extension) {
-    $this->ensureLibraryInformation($extension);
-    return $this->libraries[$extension];
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getLibraryByName($extension, $name) {
-    $this->ensureLibraryInformation($extension);
-    return isset($this->libraries[$extension][$name]) ? $this->libraries[$extension][$name] : FALSE;
-  }
-
-  /**
-   * Ensures that the libraries property is filled.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function ensureLibraryInformation($extension) {
-    $this->getCache($extension);
-    if (!isset($this->libraries[$extension])) {
-      if ($information = $this->buildLibrariesByExtension($extension)) {
-        $this->libraries[$extension] = $information;
-      }
-      else {
-        $this->libraries[$extension] = FALSE;
-      }
-      $this->setCache($extension, $this->libraries[$extension]);
-    }
-  }
-
-  /**
-   * Fills up the libraries property from cache, if available.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   */
-  protected function getCache($extension) {
-    if (!isset($this->libraries[$extension])) {
-      if ($cache = $this->cache->get('library:info:' . $extension)) {
-        $this->libraries[$extension] = $cache->data;
-      }
-    }
-  }
-
-  /**
-   * Sets the library information into a cache entry.
-   *
-   * @param string $extension
-   *   The name of the extension that registered a library.
-   *
-   * @param bool|array $information
-   *   All library definitions of the passed extension or FALSE if no
-   *   information is available.
-   */
-  protected function setCache($extension, $information) {
-    $this->cache->set('library:info:' . $extension, $information, Cache::PERMANENT, array(
-      'extension' => array(TRUE, $extension),
-      'library_info' => array(TRUE),
-    ));
-  }
-
-  /**
    * Parses and builds up all the libraries information of an extension.
    *
    * @param string $extension
@@ -135,8 +54,13 @@ protected function setCache($extension, $information) {
    * @throws \UnexpectedValueException
    *   Thrown when a js file defines a positive weight.
    */
-  protected function buildLibrariesByExtension($extension) {
+  public function buildLibrariesByExtension($extension) {
+    if (isset($this->libraries[$extension])) {
+      return $this->libraries[$extension];
+    }
+
     $this->libraries[$extension] = array();
+
     if ($extension === 'core') {
       $path = 'core';
       $extension_type = 'core';
@@ -267,21 +191,8 @@ protected function buildLibrariesByExtension($extension) {
         $library['dependencies'][$i] = $dependency;
       }
     }
-    return $this->libraries[$extension];
-  }
-
-  /**
-   * Wraps drupal_get_path().
-   */
-  protected function drupalGetPath($type, $name) {
-    return drupal_get_path($type, $name);
-  }
 
-  /**
-   * Wraps file_valid_uri().
-   */
-  protected function fileValidUri($source) {
-    return file_valid_uri($source);
+    return $this->libraries[$extension];
   }
 
   /**
@@ -309,4 +220,18 @@ protected function parseLibraryInfo($extension, $library_file) {
     $this->moduleHandler->alter('library_info', $this->libraries[$extension], $extension);
   }
 
+  /**
+   * Wraps drupal_get_path().
+   */
+  protected function drupalGetPath($type, $name) {
+    return drupal_get_path($type, $name);
+  }
+
+  /**
+   * Wraps file_valid_uri().
+   */
+  protected function fileValidUri($source) {
+    return file_valid_uri($source);
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php
new file mode 100644
index 0000000..56ea60a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace Drupal\Tests\Core\Asset;
+
+use Drupal\Core\Asset\LibraryDiscoveryCollector;
+use Drupal\Core\Cache\Cache;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the library discovery parser.
+ *
+ * @coversDefaultClass \Drupal\Core\Asset\LibraryDiscoveryCollector
+ */
+class LibraryDiscoveryCollectorTest extends UnitTestCase {
+
+  /**
+   * The mock cache backend.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $cache;
+
+  /**
+   * The mock lock backend.
+   *
+   * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $lock;
+
+  /**
+   * The mock library discovery parser.
+   *
+   * @var \Drupal\Core\Asset\LibraryDiscoveryParser|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $libraryDiscoveryParser;
+
+  /**
+   * The library discovery collector under test.
+   *
+   * @var \Drupal\Core\Asset\LibraryDiscoveryCollector
+   */
+  protected $libraryDiscoveryCollector;
+
+  /**
+   * Test library data.
+   *
+   * @var array
+   */
+  protected $libraryData = array(
+    'test_1' => array(
+      'js' => array(),
+      'css' => array(),
+    ),
+    'test_2' => array(
+      'js' => array(),
+      'css' => array(),
+    ),
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Tests \Drupal\Core\Asset\LibraryDiscoveryCollector',
+      'description' => '',
+      'group' => 'Asset handling',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
+    $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
+    $this->libraryDiscoveryParser = $this->getMockBuilder('Drupal\Core\Asset\LibraryDiscoveryParser')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $this->libraryDiscoveryCollector = new LibraryDiscoveryCollector($this->cache, $this->lock, $this->libraryDiscoveryParser);
+  }
+
+  /**
+   * Tests the resolve cache miss function.
+   *
+   * @covers ::resolveCacheMiss
+   */
+  public function testResolveCacheMiss() {
+    $this->libraryDiscoveryParser->expects($this->once())
+      ->method('buildLibrariesByExtension')
+      ->with('test')
+      ->will($this->returnValue($this->libraryData));
+
+    $this->assertSame($this->libraryData, $this->libraryDiscoveryCollector->get('test'));
+    $this->assertSame($this->libraryData, $this->libraryDiscoveryCollector->get('test'));
+  }
+
+  /**
+   * Tests the destruct method.
+   *
+   * @covers ::destruct
+   */
+  public function testDestruct() {
+    $this->libraryDiscoveryParser->expects($this->once())
+      ->method('buildLibrariesByExtension')
+      ->with('test')
+      ->will($this->returnValue($this->libraryData));
+
+    $lock_key = 'library_info:Drupal\Core\Cache\CacheCollector';
+
+    $this->lock->expects($this->once())
+      ->method('acquire')
+      ->with($lock_key)
+      ->will($this->returnValue(TRUE));
+    $this->cache->expects($this->exactly(2))
+      ->method('get')
+      ->with('library_info')
+      ->will($this->returnValue(FALSE));
+    $this->cache->expects($this->once())
+      ->method('set')
+      ->with('library_info', array('test' => $this->libraryData), Cache::PERMANENT, array('library_info' => array(TRUE)));
+    $this->lock->expects($this->once())
+      ->method('release')
+      ->with($lock_key);
+
+    // This should get data and persist the key.
+    $this->libraryDiscoveryCollector->get('test');
+    $this->libraryDiscoveryCollector->destruct();
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTestParser.php
similarity index 61%
rename from core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
rename to core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTestParser.php
index 230cac6..ea80cb9 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTestParser.php
@@ -7,8 +7,7 @@
 
 namespace Drupal\Tests\Core\Asset;
 
-use Drupal\Core\Asset\LibraryDiscovery;
-use Drupal\Core\Cache\Cache;
+use Drupal\Core\Asset\LibraryDiscoveryParser;
 use Drupal\Tests\UnitTestCase;
 
 if (!defined('DRUPAL_ROOT')) {
@@ -30,18 +29,18 @@
 }
 
 /**
- * Tests the library discovery.
+ * Tests the library discovery parser.
  *
- * @coversDefaultClass \Drupal\Core\Asset\LibraryDiscovery
+ * @coversDefaultClass \Drupal\Core\Asset\LibraryDiscoveryParser
  */
-class LibraryDiscoveryTest extends UnitTestCase {
+class LibraryDiscoveryParserTest extends UnitTestCase {
 
   /**
    * The tested library provider.
    *
-   * @var \Drupal\Core\Asset\LibraryDiscovery|\Drupal\Tests\Core\Asset\TestLibraryDiscovery
+   * @var \Drupal\Core\Asset\LibraryDiscoveryParser|\Drupal\Tests\Core\Asset\TestLibraryDiscoveryParser
    */
-  protected $libraryDiscovery;
+  protected $libraryDiscoveryParser;
 
   /**
    * The mocked cache backend.
@@ -58,18 +57,18 @@ class LibraryDiscoveryTest extends UnitTestCase {
   protected $moduleHandler;
 
   /**
-   * The mocked theme handler.
+   * The mocked lock backend..
    *
-   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
    */
-  protected $themeHandler;
+  protected $lock;
 
   /**
    * {@inheritdoc}
    */
   public static function getInfo() {
     return array(
-      'name' => 'Tests \Drupal\Core\Asset\LibraryProvider',
+      'name' => 'Tests \Drupal\Core\Asset\LibraryDiscoveryParser',
       'description' => '',
       'group' => 'Asset handling',
     );
@@ -79,19 +78,16 @@ public static function getInfo() {
    * {@inheritdoc}
    */
   protected function setUp() {
-    $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
-    $this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
-    $this->libraryDiscovery = new TestLibraryDiscovery($this->cache, $this->moduleHandler, $this->themeHandler);
+    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->moduleHandler);
   }
 
   /**
    * Tests that basic functionality works for getLibraryByName.
    *
-   * @covers ::getLibraryByName()
    * @covers ::buildLibrariesByExtension()
    */
-  public function testGetLibraryByNameSimple() {
+  public function testBuildLibrariesByExtensionSimple() {
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
       ->with('example_module')
@@ -99,9 +95,11 @@ public function testGetLibraryByNameSimple() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'example_module', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'example_module', $path);
+
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('example_module', 'example');
+    $library = $libraries['example'];
 
-    $library = $this->libraryDiscovery->getLibraryByName('example_module', 'example');
     $this->assertCount(0, $library['js']);
     $this->assertCount(1, $library['css']);
     $this->assertCount(0, $library['dependencies']);
@@ -112,33 +110,11 @@ public function testGetLibraryByNameSimple() {
   }
 
   /**
-   * Tests that basic functionality works for getLibrariesByExtension.
-   *
-   * @covers ::getLibrariesByExtension()
-   * @covers ::buildLibrariesByExtension()
-   */
-  public function testGetLibrariesByExtensionSimple() {
-    $this->moduleHandler->expects($this->atLeastOnce())
-      ->method('moduleExists')
-      ->with('example_module')
-      ->will($this->returnValue(TRUE));
-
-    $path = __DIR__ . '/library_test_files';
-    $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'example_module', $path);
-
-    $libraries = $this->libraryDiscovery->getLibrariesByExtension('example_module', 'example');
-    $this->assertCount(1, $libraries);
-    $this->assertEquals($path . '/css/example.css', $libraries['example']['css'][0]['data']);
-  }
-
-  /**
    * Tests that a theme can be used instead of a module.
    *
-   * @covers ::getLibraryByName()
    * @covers ::buildLibrariesByExtension()
    */
-  public function testGetLibraryByNameWithTheme() {
+  public function testBuildLibrariesByExtensionWithTheme() {
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
       ->with('example_theme')
@@ -146,9 +122,11 @@ public function testGetLibraryByNameWithTheme() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('theme', 'example_theme', $path);
+    $this->libraryDiscoveryParser->setPaths('theme', 'example_theme', $path);
+
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('example_theme');
+    $library = $libraries['example'];
 
-    $library = $this->libraryDiscovery->getLibraryByName('example_theme', 'example');
     $this->assertCount(0, $library['js']);
     $this->assertCount(1, $library['css']);
     $this->assertCount(0, $library['dependencies']);
@@ -158,11 +136,9 @@ public function testGetLibraryByNameWithTheme() {
   /**
    * Tests that a module with a missing library file results in FALSE.
    *
-   * @covers ::getLibraryByName()
-   * @covers ::getLibrariesByExtension()
    * @covers ::buildLibrariesByExtension()
    */
-  public function testGetLibraryWithMissingLibraryFile() {
+  public function testBuildLibrariesByExtensionWithMissingLibraryFile() {
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
       ->with('example_module')
@@ -170,10 +146,9 @@ public function testGetLibraryWithMissingLibraryFile() {
 
     $path = __DIR__ . '/library_test_files_not_existing';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'example_module', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'example_module', $path);
 
-    $this->assertFalse($this->libraryDiscovery->getLibraryByName('example_module', 'example'));
-    $this->assertFalse($this->libraryDiscovery->getLibrariesByExtension('example_module'));
+    $this->assertSame($this->libraryDiscoveryParser->buildLibrariesByExtension('example_module'), array());
   }
 
   /**
@@ -191,9 +166,9 @@ public function testInvalidLibrariesFile() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'invalid_file', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'invalid_file', $path);
 
-    $this->libraryDiscovery->getLibrariesByExtension('invalid_file');
+    $this->libraryDiscoveryParser->buildLibrariesByExtension('invalid_file');
   }
 
   /**
@@ -204,7 +179,7 @@ public function testInvalidLibrariesFile() {
    *
    * @covers ::buildLibrariesByExtension()
    */
-  public function testGetLibraryWithMissingInformation() {
+  public function testBuildLibrariesByExtensionWithMissingInformation() {
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
       ->with('example_module_missing_information')
@@ -212,9 +187,9 @@ public function testGetLibraryWithMissingInformation() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'example_module_missing_information', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'example_module_missing_information', $path);
 
-    $this->libraryDiscovery->getLibrariesByExtension('example_module_missing_information');
+    $this->libraryDiscoveryParser->buildLibrariesByExtension('example_module_missing_information');
   }
 
   /**
@@ -230,9 +205,11 @@ public function testExternalLibraries() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'external', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'external', $path);
+
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('external', 'example_external');
+    $library = $libraries['example_external'];
 
-    $library = $this->libraryDiscovery->getLibraryByName('external', 'example_external');
     $this->assertEquals($path . '/css/example_external.css', $library['css'][0]['data']);
     $this->assertEquals('3.14', $library['version']);
   }
@@ -250,9 +227,10 @@ public function testDefaultCssWeights() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'css_weights', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'css_weights', $path);
 
-    $library = $this->libraryDiscovery->getLibraryByName('css_weights', 'example');
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('css_weights');
+    $library = $libraries['example'];
     $css = $library['css'];
     $this->assertCount(10, $css);
 
@@ -289,9 +267,9 @@ public function testJsWithPositiveWeight() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'js_positive_weight', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'js_positive_weight', $path);
 
-    $this->libraryDiscovery->getLibrariesByExtension('js_positive_weight');
+    $this->libraryDiscoveryParser->buildLibrariesByExtension('js_positive_weight');
   }
 
   /**
@@ -307,9 +285,10 @@ public function testLibraryWithCssJsSetting() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'css_js_settings', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'css_js_settings', $path);
 
-    $library = $this->libraryDiscovery->getLibraryByName('css_js_settings', 'example');
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('css_js_settings');
+    $library = $libraries['example'];
 
     // Ensures that the group and type are set automatically.
     $this->assertEquals(-100, $library['js'][0]['group']);
@@ -337,9 +316,11 @@ public function testLibraryWithDependencies() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'dependencies', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'dependencies', $path);
+
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('dependencies');
+    $library = $libraries['example'];
 
-    $library = $this->libraryDiscovery->getLibraryByName('dependencies', 'example');
     $this->assertCount(2, $library['dependencies']);
     $this->assertEquals('external/example_external', $library['dependencies'][0]);
     $this->assertEquals('example_module/example', $library['dependencies'][1]);
@@ -358,12 +339,14 @@ public function testLibraryWithDataTypes() {
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'data_types', $path);
+    $this->libraryDiscoveryParser->setPaths('module', 'data_types', $path);
 
-    $this->libraryDiscovery->setFileValidUri('public://test.css', TRUE);
-    $this->libraryDiscovery->setFileValidUri('public://test2.css', FALSE);
+    $this->libraryDiscoveryParser->setFileValidUri('public://test.css', TRUE);
+    $this->libraryDiscoveryParser->setFileValidUri('public://test2.css', FALSE);
+
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('data_types');
+    $library = $libraries['example'];
 
-    $library = $this->libraryDiscovery->getLibraryByName('data_types', 'example');
     $this->assertCount(5, $library['css']);
     $this->assertEquals('external', $library['css'][0]['type']);
     $this->assertEquals('http://example.com/test.css', $library['css'][0]['data']);
@@ -385,82 +368,17 @@ public function testStaticCache() {
       ->method('moduleExists')
       ->with('example_module')
       ->will($this->returnValue(TRUE));
-    $this->cache->expects($this->once())
-      ->method('get')
-      ->with('library:info:' . 'example_module')
-      ->will($this->returnValue(NULL));
-
-    $path = __DIR__ . '/library_test_files';
-    $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'example_module', $path);
-
-    $library = $this->libraryDiscovery->getLibraryByName('example_module', 'example');
-    $this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
-
-    $library = $this->libraryDiscovery->getLibraryByName('example_module', 'example');
-    $this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
-  }
-
-  /**
-   * Tests the external cache.
-   *
-   * @covers ::getCache()
-   */
-  public function testExternalCache() {
-    // Ensure that the module handler does not need to be touched.
-    $this->moduleHandler->expects($this->never())
-      ->method('moduleExists');
 
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen(DRUPAL_ROOT) + 1);
+    $this->libraryDiscoveryParser->setPaths('module', 'example_module', $path);
 
-    // Setup a cache entry which will be retrieved, but just once, so the static
-    // cache still works.
-    $this->cache->expects($this->once())
-      ->method('get')
-      ->with('library:info:' . 'example_module')
-      ->will($this->returnValue((object) array(
-        'data' => array(
-          'example' => array(
-            'css' => array(
-              array(
-                'data' => $path . '/css/example.css',
-              ),
-            ),
-          ),
-        )
-      )));
-
-    $library = $this->libraryDiscovery->getLibraryByName('example_module', 'example');
-    $this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
-
-    $library = $this->libraryDiscovery->getLibraryByName('example_module', 'example');
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('example_module');
+    $library = $libraries['example'];
     $this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
-  }
-
-  /**
-   * Tests setting the external cache.
-   *
-   * @covers ::setCache()
-   */
-  public function testSetCache() {
-    $this->moduleHandler->expects($this->once())
-      ->method('moduleExists')
-      ->with('example_module')
-      ->will($this->returnValue(TRUE));
-
-    $path = __DIR__ . '/library_test_files';
-    $path = substr($path, strlen(DRUPAL_ROOT) + 1);
-    $this->libraryDiscovery->setPaths('module', 'example_module', $path);
-
-    $this->cache->expects($this->once())
-      ->method('set')
-      ->with('library:info:example_module', $this->isType('array'), Cache::PERMANENT, array(
-      'extension' => array(TRUE, 'example_module'),
-      'library_info' => array(TRUE),
-    ));
 
-    $library = $this->libraryDiscovery->getLibraryByName('example_module', 'example');
+    $libraries = $this->libraryDiscoveryParser->buildLibrariesByExtension('example_module');
+    $library = $libraries['example'];
     $this->assertEquals($path . '/css/example.css', $library['css'][0]['data']);
   }
 
@@ -469,7 +387,7 @@ public function testSetCache() {
 /**
  * Wraps the tested class to mock the external dependencies.
  */
-class TestLibraryDiscovery extends LibraryDiscovery {
+class TestLibraryDiscoveryParser extends LibraryDiscoveryParser {
 
   protected $paths;
 
