Browse Source

Polishing

pull/28468/head
Sam Brannen 4 years ago
parent
commit
fe7c6f075b
  1. 4
      spring-beans/src/main/java/org/springframework/beans/factory/aot/AotFactoriesLoader.java
  2. 18
      spring-beans/src/test/java/org/springframework/beans/factory/aot/AotFactoriesLoaderTests.java
  3. 70
      spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java
  4. 20
      spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoaderRuntimeHintsRegistrar.java

4
spring-beans/src/main/java/org/springframework/beans/factory/aot/AotFactoriesLoader.java

@ -30,8 +30,8 @@ import org.springframework.util.Assert; @@ -30,8 +30,8 @@ import org.springframework.util.Assert;
/**
* AOT specific factory loading mechanism for internal use within the framework.
* <p>
* Loads and instantiates factories of a given type from
*
* <p>Loads and instantiates factories of a given type from
* {@value #FACTORIES_RESOURCE_LOCATION} and merges them with matching beans
* from a {@link ListableBeanFactory}.
*

18
spring-beans/src/test/java/org/springframework/beans/factory/aot/AotFactoriesLoaderTests.java

@ -56,22 +56,14 @@ class AotFactoriesLoaderTests { @@ -56,22 +56,14 @@ class AotFactoriesLoaderTests {
beanFactory.registerSingleton("b1", new TestFactoryImpl(0, "b1"));
beanFactory.registerSingleton("b2", new TestFactoryImpl(2, "b2"));
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
springFactoriesLoader.addInstance(TestFactory.class,
new TestFactoryImpl(1, "l1"));
springFactoriesLoader.addInstance(TestFactory.class,
new TestFactoryImpl(3, "l2"));
AotFactoriesLoader loader = new AotFactoriesLoader(beanFactory,
springFactoriesLoader);
springFactoriesLoader.addInstance(TestFactory.class, new TestFactoryImpl(1, "l1"));
springFactoriesLoader.addInstance(TestFactory.class, new TestFactoryImpl(3, "l2"));
AotFactoriesLoader loader = new AotFactoriesLoader(beanFactory, springFactoriesLoader);
List<TestFactory> loaded = loader.load(TestFactory.class);
assertThat(loaded).hasSize(4);
assertThat(loaded.get(0)).hasToString("b1");
assertThat(loaded.get(1)).hasToString("l1");
assertThat(loaded.get(2)).hasToString("b2");
assertThat(loaded.get(3)).hasToString("l2");
assertThat(loaded).map(Object::toString).containsExactly("b1", "l1", "b2", "l2");
}
static interface TestFactory {
interface TestFactory {
}
static class TestFactoryImpl implements TestFactory, Ordered {

70
spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoader.java

@ -18,7 +18,6 @@ package org.springframework.core.io.support; @@ -18,7 +18,6 @@ package org.springframework.core.io.support;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
@ -69,15 +68,16 @@ import org.springframework.util.StringUtils; @@ -69,15 +68,16 @@ import org.springframework.util.StringUtils;
*
* where {@code example.MyService} is the name of the interface, and {@code MyServiceImpl1}
* and {@code MyServiceImpl2} are two implementations.
* <p>
* Implementation classes <b>must</b> have a single resolvable constructor that will
*
* <p>Implementation classes <b>must</b> have a single resolvable constructor that will
* be used to create the instance, either:
* <ul>
* <li>a primary or single constructor</li>
* <li>a single public constructor</li>
* <li>the default constructor</li>
* </ul>
* If the resolvable constructor has arguments, a suitable {@link ArgumentResolver
*
* <p>If the resolvable constructor has arguments, a suitable {@link ArgumentResolver
* ArgumentResolver} should be provided. To customize how instantiation failures
* are handled, consider providing a {@link FailureHandler FailureHandler}.
*
@ -223,7 +223,7 @@ public class SpringFactoriesLoader { @@ -223,7 +223,7 @@ public class SpringFactoriesLoader {
try {
Class<?> factoryImplementationClass = ClassUtils.forName(implementationName, this.classLoader);
Assert.isTrue(type.isAssignableFrom(factoryImplementationClass),
() -> "Class [" + implementationName + "] is not assignable to factory type [" + type.getName() + "]");
() -> "Class [%s] is not assignable to factory type [%s]".formatted(implementationName, type.getName()));
FactoryInstantiator<T> factoryInstantiator = FactoryInstantiator.forClass(factoryImplementationClass);
return factoryInstantiator.instantiate(argumentResolver);
}
@ -319,20 +319,12 @@ public class SpringFactoriesLoader { @@ -319,20 +319,12 @@ public class SpringFactoriesLoader {
*/
public static SpringFactoriesLoader forResourceLocation(@Nullable ClassLoader classLoader, String resourceLocation) {
Assert.hasText(resourceLocation, "'resourceLocation' must not be empty");
ClassLoader resourceClassLoader = (classLoader != null) ? classLoader
: SpringFactoriesLoader.class.getClassLoader();
Map<String, SpringFactoriesLoader> loaders = SpringFactoriesLoader.cache.get(resourceClassLoader);
if (loaders == null) {
loaders = new ConcurrentReferenceHashMap<>();
SpringFactoriesLoader.cache.put(resourceClassLoader, loaders);
}
SpringFactoriesLoader loader = loaders.get(resourceLocation);
if (loader == null) {
Map<String, List<String>> factories = loadFactoriesResource(resourceClassLoader, resourceLocation);
loader = new SpringFactoriesLoader(classLoader, factories);
loaders.put(resourceLocation, loader);
}
return loader;
ClassLoader resourceClassLoader = (classLoader != null ? classLoader :
SpringFactoriesLoader.class.getClassLoader());
Map<String, SpringFactoriesLoader> loaders = SpringFactoriesLoader.cache.computeIfAbsent(
resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());
return loaders.computeIfAbsent(resourceLocation, key ->
new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation)));
}
static Map<String, List<String>> loadFactoriesResource(ClassLoader classLoader, String resourceLocation) {
@ -394,7 +386,8 @@ public class SpringFactoriesLoader { @@ -394,7 +386,8 @@ public class SpringFactoriesLoader {
@SuppressWarnings("unchecked")
static <T> FactoryInstantiator<T> forClass(Class<?> factoryImplementationClass) {
Constructor<?> constructor = findConstructor(factoryImplementationClass);
Assert.state(constructor != null, "Class [" + factoryImplementationClass.getName() + "] has no suitable constructor");
Assert.state(constructor != null, () ->
"Class [%s] has no suitable constructor".formatted(factoryImplementationClass.getName()));
return new FactoryInstantiator<>((Constructor<T>) constructor);
}
@ -413,8 +406,8 @@ public class SpringFactoriesLoader { @@ -413,8 +406,8 @@ public class SpringFactoriesLoader {
@Nullable
private static Constructor<?> findPrimaryKotlinConstructor(Class<?> factoryImplementationClass) {
return (isKotlinType(factoryImplementationClass)
? KotlinDelegate.findPrimaryConstructor(factoryImplementationClass) : null);
return (isKotlinType(factoryImplementationClass) ?
KotlinDelegate.findPrimaryConstructor(factoryImplementationClass) : null);
}
private static boolean isKotlinType(Class<?> factoryImplementationClass) {
@ -440,12 +433,12 @@ public class SpringFactoriesLoader { @@ -440,12 +433,12 @@ public class SpringFactoriesLoader {
/**
* Inner class to avoid a hard dependency on Kotlin at runtime.
* Nested class to avoid a hard dependency on Kotlin at runtime.
*/
private static class KotlinDelegate {
@Nullable
public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
try {
KFunction<T> primaryConstructor = KClasses.getPrimaryConstructor(JvmClassMappingKt.getKotlinClass(clazz));
if (primaryConstructor != null) {
@ -462,8 +455,7 @@ public class SpringFactoriesLoader { @@ -462,8 +455,7 @@ public class SpringFactoriesLoader {
return null;
}
public static <T> T instantiate(Constructor<T> constructor, Object[] args)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
static <T> T instantiate(Constructor<T> constructor, Object[] args) throws Exception {
KFunction<T> kotlinConstructor = ReflectJvmMapping.getKotlinFunction(constructor);
if (kotlinConstructor == null) {
return constructor.newInstance(args);
@ -483,7 +475,7 @@ public class SpringFactoriesLoader { @@ -483,7 +475,7 @@ public class SpringFactoriesLoader {
private static Map<KParameter, Object> convertArgs(Object[] args, List<KParameter> parameters) {
Map<KParameter, Object> result = CollectionUtils.newHashMap(parameters.size());
Assert.isTrue(args.length <= parameters.size(),
"Number of provided arguments should be less of equals than number of constructor parameters");
"Number of provided arguments should be less than or equal to the number of constructor parameters");
for (int i = 0; i < args.length; i++) {
if (!parameters.get(i).isOptional() || args[i] != null) {
result.put(parameters.get(i), args[i]);
@ -552,12 +544,12 @@ public class SpringFactoriesLoader { @@ -552,12 +544,12 @@ public class SpringFactoriesLoader {
default ArgumentResolver and(ArgumentResolver argumentResolver) {
return from(type -> {
Object resolved = resolve(type);
return (resolved != null) ? resolved : argumentResolver.resolve(type);
return (resolved != null ? resolved : argumentResolver.resolve(type));
});
}
/**
* Factory method that returns a {@link ArgumentResolver} that always
* Factory method that returns an {@link ArgumentResolver} that always
* returns {@code null}.
* @return a new {@link ArgumentResolver} instance
*/
@ -566,7 +558,7 @@ public class SpringFactoriesLoader { @@ -566,7 +558,7 @@ public class SpringFactoriesLoader {
}
/**
* Factory method that can be used to create a {@link ArgumentResolver}
* Factory method that can be used to create an {@link ArgumentResolver}
* that resolves only the given type.
* @param <T> the argument type
* @param type the argument type
@ -578,7 +570,7 @@ public class SpringFactoriesLoader { @@ -578,7 +570,7 @@ public class SpringFactoriesLoader {
}
/**
* Factory method that can be used to create a {@link ArgumentResolver}
* Factory method that can be used to create an {@link ArgumentResolver}
* that resolves only the given type.
* @param <T> the argument type
* @param type the argument type
@ -643,8 +635,8 @@ public class SpringFactoriesLoader { @@ -643,8 +635,8 @@ public class SpringFactoriesLoader {
}
/**
* Return a new {@link FailureHandler} that handles
* errors by throwing an exception.
* Return a new {@link FailureHandler} that handles errors by throwing an
* exception.
* @param exceptionFactory factory used to create the exception
* @return a new {@link FailureHandler} instance
*/
@ -655,8 +647,8 @@ public class SpringFactoriesLoader { @@ -655,8 +647,8 @@ public class SpringFactoriesLoader {
}
/**
* Return a new {@link FailureHandler} that handles
* errors by logging trace messages.
* Return a new {@link FailureHandler} that handles errors by logging trace
* messages.
* @param logger the logger used to log message
* @return a new {@link FailureHandler} instance
*/
@ -665,15 +657,15 @@ public class SpringFactoriesLoader { @@ -665,15 +657,15 @@ public class SpringFactoriesLoader {
}
/**
* Return a new {@link FailureHandler} that handles
* errors with using a standard formatted message.
* Return a new {@link FailureHandler} that handles errors using a standard
* formatted message.
* @param messageHandler the message handler used to handle the problem
* @return a new {@link FailureHandler} instance
*/
static FailureHandler handleMessage(BiConsumer<Supplier<String>, Throwable> messageHandler) {
return (factoryType, factoryImplementationName, failure) -> {
Supplier<String> message = () -> "Unable to instantiate factory class [" + factoryImplementationName +
"] for factory type [" + factoryType.getName() + "]";
Supplier<String> message = () -> "Unable to instantiate factory class [%s] for factory type [%s]"
.formatted(factoryImplementationName, factoryType.getName());
messageHandler.accept(message, failure);
};
}

20
spring-core/src/main/java/org/springframework/core/io/support/SpringFactoriesLoaderRuntimeHintsRegistrar.java

@ -41,11 +41,11 @@ import org.springframework.util.ClassUtils; @@ -41,11 +41,11 @@ import org.springframework.util.ClassUtils;
*/
class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistrar {
private static List<String> RESOURCE_LOCATIONS = List
.of(SpringFactoriesLoader.FACTORIES_RESOURCE_LOCATION);
private static List<String> RESOURCE_LOCATIONS =
List.of(SpringFactoriesLoader.FACTORIES_RESOURCE_LOCATION);
private static final Consumer<TypeHint.Builder> HINT = builder -> builder
.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
private static final Consumer<TypeHint.Builder> HINT = builder ->
builder.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
private final Log logger = LogFactory.getLog(SpringFactoriesLoaderRuntimeHintsRegistrar.class);
@ -57,11 +57,10 @@ class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistra @@ -57,11 +57,10 @@ class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistra
}
}
private void registerHints(RuntimeHints hints, ClassLoader classLoader,
String resourceLocation) {
private void registerHints(RuntimeHints hints, ClassLoader classLoader, String resourceLocation) {
hints.resources().registerPattern(resourceLocation);
Map<String, List<String>> factories = SpringFactoriesLoader
.loadFactoriesResource(classLoader, resourceLocation);
Map<String, List<String>> factories =
SpringFactoriesLoader.loadFactoriesResource(classLoader, resourceLocation);
factories.forEach((factoryClassName, implementationClassNames) ->
registerHints(hints, classLoader, factoryClassName, implementationClassNames));
}
@ -69,7 +68,7 @@ class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistra @@ -69,7 +68,7 @@ class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistra
private void registerHints(RuntimeHints hints, ClassLoader classLoader,
String factoryClassName, List<String> implementationClassNames) {
Class<?> factoryClass = resolveClassName(classLoader, factoryClassName);
if(factoryClass == null) {
if (factoryClass == null) {
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("Skipping factories for [%s]", factoryClassName));
}
@ -83,7 +82,8 @@ class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistra @@ -83,7 +82,8 @@ class SpringFactoriesLoaderRuntimeHintsRegistrar implements RuntimeHintsRegistra
Class<?> implementationType = resolveClassName(classLoader, implementationClassName);
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("%s factory type [%s] and implementation [%s]",
(implementationType != null) ? "Processing" : "Skipping", factoryClassName, implementationClassName));
(implementationType != null ? "Processing" : "Skipping"), factoryClassName,
implementationClassName));
}
if (implementationType != null) {
hints.reflection().registerType(implementationType, HINT);

Loading…
Cancel
Save