From 859953fe8152ded817813dc56ee2b2fdfd86f43f Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Wed, 29 Apr 2020 14:40:40 +0200 Subject: [PATCH] Use same default ClassLoader in SpringFactoriesLoader Prior to this commit, the loadFactoryNames() and loadFactories() methods in SpringFactoriesLoader effectively used a different default ClassLoader. This commit ensures that the ClassLoader for SpringFactoriesLoader.class is now consistently used as the default ClassLoader. Closes gh-24992 --- .../io/support/SpringFactoriesLoader.java | 14 ++++++++------ .../support/SpringFactoriesLoaderTests.java | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) 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 69aa6c12ea..c73e775b39 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 @@ -70,7 +70,7 @@ public final class SpringFactoriesLoader { private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class); - private static final Map>> cache = new ConcurrentReferenceHashMap<>(); + static final Map>> cache = new ConcurrentReferenceHashMap<>(); private SpringFactoriesLoader() { @@ -124,11 +124,15 @@ public final class SpringFactoriesLoader { * @see #loadFactories */ public static List loadFactoryNames(Class factoryType, @Nullable ClassLoader classLoader) { + ClassLoader classLoaderToUse = classLoader; + if (classLoaderToUse == null) { + classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); + } String factoryTypeName = factoryType.getName(); - return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); + return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList()); } - private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { + private static Map> loadSpringFactories(ClassLoader classLoader) { Map> result = cache.get(classLoader); if (result != null) { return result; @@ -136,9 +140,7 @@ public final class SpringFactoriesLoader { result = new HashMap<>(); try { - Enumeration urls = (classLoader != null ? - classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : - ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); + Enumeration urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); diff --git a/spring-core/src/test/java/org/springframework/core/io/support/SpringFactoriesLoaderTests.java b/spring-core/src/test/java/org/springframework/core/io/support/SpringFactoriesLoaderTests.java index aff7c7fea1..913943da5b 100644 --- a/spring-core/src/test/java/org/springframework/core/io/support/SpringFactoriesLoaderTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/support/SpringFactoriesLoaderTests.java @@ -19,6 +19,8 @@ package org.springframework.core.io.support; import java.lang.reflect.Modifier; import java.util.List; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -33,6 +35,23 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException */ class SpringFactoriesLoaderTests { + @BeforeAll + static void clearCache() { + SpringFactoriesLoader.cache.clear(); + assertThat(SpringFactoriesLoader.cache).isEmpty(); + } + + @AfterAll + static void checkCache() { + assertThat(SpringFactoriesLoader.cache).hasSize(1); + } + + @Test + void loadFactoryNames() { + List factoryNames = SpringFactoriesLoader.loadFactoryNames(DummyFactory.class, null); + assertThat(factoryNames).containsExactlyInAnyOrder(MyDummyFactory1.class.getName(), MyDummyFactory2.class.getName()); + } + @Test void loadFactoriesWithNoRegisteredImplementations() { List factories = SpringFactoriesLoader.loadFactories(Integer.class, null);