diff --git a/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java b/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java index ef4525214f..01d1ca6e86 100644 --- a/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java +++ b/spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,17 +20,21 @@ import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; import java.util.List; +import java.util.Map; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.io.UrlResource; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import org.springframework.util.ConcurrentReferenceHashMap; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -58,6 +62,8 @@ public abstract class SpringFactoriesLoader { private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class); + private static Map> cache = new ConcurrentReferenceHashMap<>(); + /** * The location to look for factories. *

Can be present in multiple JAR files. @@ -107,21 +113,36 @@ public abstract class SpringFactoriesLoader { */ public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); + return loadSpringFactories(classLoader).getOrDefault(factoryClassName, + Collections.emptyList()); + } + + private static Map> loadSpringFactories( + ClassLoader classLoader) { + MultiValueMap result = cache.get(classLoader); + if (result != null) + return result; try { - Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : - ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); - List result = new ArrayList<>(); + Enumeration urls = (classLoader != null + ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) + : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); + result = new LinkedMultiValueMap<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); - Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); - String factoryClassNames = properties.getProperty(factoryClassName); - result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); + UrlResource resource = new UrlResource(url); + Properties properties = PropertiesLoaderUtils.loadProperties(resource); + for (Map.Entry entry : properties.entrySet()) { + List factoryClassNames = Arrays.asList( + StringUtils.commaDelimitedListToStringArray((String) entry.getValue())); + result.addAll((String) entry.getKey(), factoryClassNames); + } } + cache.put(classLoader, result); return result; } catch (IOException ex) { - throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + - "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); + throw new IllegalArgumentException("Unable to load factories from location [" + + FACTORIES_RESOURCE_LOCATION + "]", ex); } }