Skip to content

Commit

Permalink
Cache types in ConstructorInstanceFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
elonazoulay committed Mar 2, 2024
1 parent 344bb93 commit a067a4c
Showing 1 changed file with 6 additions and 35 deletions.
Expand Up @@ -22,31 +22,25 @@
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.jdbi.v3.core.internal.exceptions.Unchecked;

import static java.util.Collections.synchronizedMap;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toUnmodifiableList;

class ConstructorInstanceFactory<T> extends InstanceFactory<T> {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final Map<Constructor, ConstructorHandleAndTypes> CONSTRUCTOR_CACHE = synchronizedMap(new WeakHashMap<>());

private final Constructor<T> constructor;
private final List<Type> types;
private final MethodHandle constructorHandle;

ConstructorInstanceFactory(Constructor<T> constructor) {
super(constructor);
this.constructor = requireNonNull(constructor, "constructor is null");
ConstructorHandleAndTypes constructorHandleAndTypes = getConstructorHandleAndTypes(constructor, super::getTypes);
this.types = constructorHandleAndTypes.getTypes();
this.constructorHandle = constructorHandleAndTypes.getConstructorHandle();
this.types = extractTypes(constructor, super::getTypes);
this.constructorHandle = getConstructorMethodHandle(constructor);
}

@Override
Expand Down Expand Up @@ -88,18 +82,13 @@ private static <T> boolean isGenericInformationLost(Constructor<T> factory) {
return lossDetected;
}

private static <T> ConstructorHandleAndTypes getConstructorHandleAndTypes(Constructor<T> constructor, Supplier<List<Type>> defaultSupplier) {
return CONSTRUCTOR_CACHE.computeIfAbsent(constructor, ctor -> computeConstructorHandleAndTypes(ctor, defaultSupplier));
}

private static <T> ConstructorHandleAndTypes computeConstructorHandleAndTypes(Constructor<T> constructor, Supplier<List<Type>> defaultSupplier) {
MethodHandle constructorMethodHandle = getConstructorMethodHandle(constructor);
private static <T> List<Type> extractTypes(Constructor<T> constructor, Supplier<List<Type>> defaultSupplier) {
if (isGenericInformationLost(constructor)) {
return new ConstructorHandleAndTypes(constructorMethodHandle, getFields(constructor)
return getFields(constructor)
.map(Field::getGenericType)
.collect(toUnmodifiableList()));
.collect(toUnmodifiableList());
}
return new ConstructorHandleAndTypes(constructorMethodHandle, defaultSupplier.get());
return defaultSupplier.get();
}

private static <T> MethodHandle getConstructorMethodHandle(Constructor<T> constructor) {
Expand All @@ -114,22 +103,4 @@ private static <T> Stream<Field> getFields(Constructor<T> constructor) {
return Arrays.stream(constructor.getDeclaringClass().getDeclaredFields())
.filter(field -> !Modifier.isStatic(field.getModifiers()));
}

private static class ConstructorHandleAndTypes {
private final MethodHandle constructorHandle;
private final List<Type> types;

ConstructorHandleAndTypes(MethodHandle constructorHandle, List<Type> types) {
this.constructorHandle = requireNonNull(constructorHandle, "constructorHandle is null");
this.types = requireNonNull(types, "types is null");
}

public MethodHandle getConstructorHandle() {
return constructorHandle;
}

public List<Type> getTypes() {
return types;
}
}
}

0 comments on commit a067a4c

Please sign in to comment.