Skip to content

Commit

Permalink
Merge pull request #2416 from hgschmie/sqlobject-performance
Browse files Browse the repository at this point in the history
Improve config customizer performance
  • Loading branch information
hgschmie committed Jun 30, 2023
2 parents 8364511 + f4df5c7 commit c247ce5
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.jdbi.v3.core.config.ConfigCustomizer;
import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.annotation.UseExtensionConfigurer;
import org.jdbi.v3.core.internal.JdbiClassUtils;
import org.jdbi.v3.core.internal.exceptions.CheckedCallable;

import static java.lang.String.format;

Expand All @@ -41,34 +43,49 @@ public Collection<ConfigCustomizer> forExtensionType(Class<?> extensionType) {
final ConfigurerMethod forType = (configurer, config, annotation) -> configurer.configureForType(config, annotation, extensionType);

// build a configurer for the type and all supertypes. This processes all annotations on classes and interfaces
return buildConfigCustomizer(Stream.concat(JdbiClassUtils.superTypes(extensionType), Stream.of(extensionType)), forType);
return buildConfigCustomizer(extensionType, Stream.concat(JdbiClassUtils.superTypes(extensionType), Stream.of(extensionType)), forType);
}

@Override
public Collection<ConfigCustomizer> forExtensionMethod(Class<?> extensionType, Method method) {
final ConfigurerMethod forMethod = (configurer, config, annotation) -> configurer.configureForMethod(config, annotation, extensionType, method);
// build a configurer that processes all annotations on the method itself.
return buildConfigCustomizer(Stream.of(method), forMethod);
return buildConfigCustomizer(extensionType, Stream.of(method), forMethod);
}

private static Collection<ConfigCustomizer> buildConfigCustomizer(Stream<AnnotatedElement> elements, ConfigurerMethod consumer) {
private static Collection<ConfigCustomizer> buildConfigCustomizer(Class<?> extensionType, Stream<AnnotatedElement> elements, ConfigurerMethod consumer) {
return elements.flatMap(ae -> Arrays.stream(ae.getAnnotations()))
.filter(a -> a.annotationType().isAnnotationPresent(UseExtensionConfigurer.class))
.map(a -> {
UseExtensionConfigurer meta = a.annotationType().getAnnotation(UseExtensionConfigurer.class);
Class<? extends ExtensionConfigurer> klass = meta.value();

try {
ExtensionConfigurer configurer = klass.getConstructor().newInstance();
return (ConfigCustomizer) config -> consumer.configure(configurer, config, a);
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException(format("Unable to instantiate class %s", klass), e);
}
ExtensionConfigurer configurer = createConfigurer(klass, extensionType, a);
return (ConfigCustomizer) config -> consumer.configure(configurer, config, a);

})
.collect(Collectors.toList());
}

private static ExtensionConfigurer createConfigurer(Class<? extends ExtensionConfigurer> configurerType, Class<?> extensionType, Annotation annotation) {

CheckedCallable[] callables = {
() -> configurerType.getConstructor().newInstance(),
() -> configurerType.getConstructor(Annotation.class).newInstance(annotation),
() -> configurerType.getConstructor(Annotation.class, Class.class).newInstance(annotation, extensionType)
};

for (CheckedCallable<ExtensionConfigurer> callable : callables) {
Optional<ExtensionConfigurer> handler = JdbiClassUtils.createInstanceIfPossible(callable);
if (handler.isPresent()) {
return handler.get();
}
}

throw new IllegalStateException(format("ExtensionConfigurer class %s cannot be instantiated. "
+ "Expected a constructor with parameters (Annotation) or ().", configurerType));
}

private interface ConfigurerMethod {

void configure(ExtensionConfigurer configurer, ConfigRegistry config, Annotation annotation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,38 @@
package org.jdbi.v3.sqlobject.config.internal;

import java.lang.annotation.Annotation;
import java.util.stream.Stream;
import java.util.ArrayList;
import java.util.List;

import org.jdbi.v3.core.argument.ArgumentFactory;
import org.jdbi.v3.core.argument.Arguments;
import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.ExtensionConfigurer;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.sqlobject.config.RegisterArgumentFactories;
import org.jdbi.v3.sqlobject.config.RegisterArgumentFactory;

public class RegisterArgumentFactoriesImpl extends SimpleExtensionConfigurer {

private final List<ArgumentFactory> argumentFactories;

public RegisterArgumentFactoriesImpl(Annotation annotation) {
final RegisterArgumentFactories registerArgumentFactories = (RegisterArgumentFactories) annotation;
this.argumentFactories = new ArrayList<>(registerArgumentFactories.value().length);

for (RegisterArgumentFactory registerArgumentFactory : registerArgumentFactories.value()) {
final Class<? extends ArgumentFactory> klass = registerArgumentFactory.value();

try {
argumentFactories.add(klass.getConstructor().newInstance());
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate column mapper class " + klass, e);
}
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
ExtensionConfigurer delegate = new RegisterArgumentFactoryImpl();
RegisterArgumentFactories factories = (RegisterArgumentFactories) annotation;
Stream.of(factories.value()).forEach(anno -> delegate.configureForType(config, anno, sqlObjectType));
Arguments arguments = config.get(Arguments.class);
argumentFactories.forEach(arguments::register);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,29 @@

import java.lang.annotation.Annotation;

import org.jdbi.v3.core.argument.ArgumentFactory;
import org.jdbi.v3.core.argument.Arguments;
import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.sqlobject.config.RegisterArgumentFactory;

public class RegisterArgumentFactoryImpl extends SimpleExtensionConfigurer {

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
private final ArgumentFactory argumentFactory;

public RegisterArgumentFactoryImpl(Annotation annotation) {
RegisterArgumentFactory registerArgumentFactory = (RegisterArgumentFactory) annotation;
Arguments arguments = config.get(Arguments.class);
final Class<? extends ArgumentFactory> klass = registerArgumentFactory.value();

try {
arguments.register(registerArgumentFactory.value().getConstructor().newInstance());
this.argumentFactory = klass.getConstructor().newInstance();
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate argument factory class " + registerArgumentFactory.value(), e);
throw new IllegalStateException("Unable to instantiate column mapper class " + klass, e);
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
config.get(Arguments.class).register(argumentFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,38 @@
package org.jdbi.v3.sqlobject.config.internal;

import java.lang.annotation.Annotation;
import java.util.stream.Stream;
import java.util.ArrayList;
import java.util.List;

import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.ExtensionConfigurer;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.core.mapper.ColumnMapperFactory;
import org.jdbi.v3.core.mapper.ColumnMappers;
import org.jdbi.v3.sqlobject.config.RegisterColumnMapperFactories;
import org.jdbi.v3.sqlobject.config.RegisterColumnMapperFactory;

public class RegisterColumnMapperFactoriesImpl extends SimpleExtensionConfigurer {

private final List<ColumnMapperFactory> columnMapperFactories;

public RegisterColumnMapperFactoriesImpl(Annotation annotation) {
final RegisterColumnMapperFactories registerColumnMapperFactories = (RegisterColumnMapperFactories) annotation;
this.columnMapperFactories = new ArrayList<>(registerColumnMapperFactories.value().length);

for (RegisterColumnMapperFactory registerColumnMapperFactory : registerColumnMapperFactories.value()) {
final Class<? extends ColumnMapperFactory> klass = registerColumnMapperFactory.value();

try {
columnMapperFactories.add(klass.getConstructor().newInstance());
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate row mapper factory class " + klass, e);
}
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
ExtensionConfigurer delegate = new RegisterColumnMapperFactoryImpl();

RegisterColumnMapperFactories registerColumnMapperFactories = (RegisterColumnMapperFactories) annotation;
Stream.of(registerColumnMapperFactories.value()).forEach(anno -> delegate.configureForType(config, anno, sqlObjectType));
ColumnMappers columnMappers = config.get(ColumnMappers.class);
columnMapperFactories.forEach(columnMappers::register);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,22 @@

public class RegisterColumnMapperFactoryImpl extends SimpleExtensionConfigurer {

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
RegisterColumnMapperFactory registerColumnMapperFactory = (RegisterColumnMapperFactory) annotation;
private final ColumnMapperFactory columnMapperFactory;

public RegisterColumnMapperFactoryImpl(Annotation annotation) {
final RegisterColumnMapperFactory registerColumnMapperFactory = (RegisterColumnMapperFactory) annotation;
final Class<? extends ColumnMapperFactory> klass = registerColumnMapperFactory.value();

try {
ColumnMapperFactory factory = registerColumnMapperFactory.value().getConstructor().newInstance();
config.get(ColumnMappers.class).register(factory);
this.columnMapperFactory = klass.getConstructor().newInstance();
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate column mapper factory class " + registerColumnMapperFactory.value(), e);
throw new IllegalStateException("Unable to instantiate column mapper factory class " + klass, e);
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
ColumnMappers columnMappers = config.get(ColumnMappers.class);
columnMappers.register(columnMapperFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,27 @@

import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.core.mapper.ColumnMapper;
import org.jdbi.v3.core.mapper.ColumnMappers;
import org.jdbi.v3.sqlobject.config.RegisterColumnMapper;

public class RegisterColumnMapperImpl extends SimpleExtensionConfigurer {

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
private final ColumnMapper<?> columnMapper;

public RegisterColumnMapperImpl(Annotation annotation) {
RegisterColumnMapper registerColumnMapper = (RegisterColumnMapper) annotation;
ColumnMappers mappers = config.get(ColumnMappers.class);
final Class<? extends ColumnMapper<?>> klass = registerColumnMapper.value();

try {
mappers.register(registerColumnMapper.value().getConstructor().newInstance());
this.columnMapper = klass.getConstructor().newInstance();
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate column mapper class " + registerColumnMapper.value(), e);
throw new IllegalStateException("Unable to instantiate column mapper class " + klass, e);
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
config.get(ColumnMappers.class).register(columnMapper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,38 @@
package org.jdbi.v3.sqlobject.config.internal;

import java.lang.annotation.Annotation;
import java.util.stream.Stream;
import java.util.ArrayList;
import java.util.List;

import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.ExtensionConfigurer;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.core.mapper.ColumnMapper;
import org.jdbi.v3.core.mapper.ColumnMappers;
import org.jdbi.v3.sqlobject.config.RegisterColumnMapper;
import org.jdbi.v3.sqlobject.config.RegisterColumnMappers;

public class RegisterColumnMappersImpl extends SimpleExtensionConfigurer {

private final List<ColumnMapper<?>> columnMappers;

public RegisterColumnMappersImpl(Annotation annotation) {
final RegisterColumnMappers registerColumnMappers = (RegisterColumnMappers) annotation;
this.columnMappers = new ArrayList<>(registerColumnMappers.value().length);

for (RegisterColumnMapper registerColumnMapper : registerColumnMappers.value()) {
final Class<? extends ColumnMapper<?>> klass = registerColumnMapper.value();

try {
columnMappers.add(klass.getConstructor().newInstance());
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate column mapper class " + klass, e);
}
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
ExtensionConfigurer delegate = new RegisterColumnMapperImpl();

RegisterColumnMappers registerColumnMappers = (RegisterColumnMappers) annotation;
Stream.of(registerColumnMappers.value()).forEach(anno -> delegate.configureForType(config, anno, sqlObjectType));
ColumnMappers columnMappersConfig = config.get(ColumnMappers.class);
columnMappers.forEach(columnMappersConfig::register);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,38 @@
package org.jdbi.v3.sqlobject.config.internal;

import java.lang.annotation.Annotation;
import java.util.stream.Stream;
import java.util.ArrayList;
import java.util.List;

import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.ExtensionConfigurer;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.core.mapper.RowMapperFactory;
import org.jdbi.v3.core.mapper.RowMappers;
import org.jdbi.v3.sqlobject.config.RegisterRowMapperFactories;
import org.jdbi.v3.sqlobject.config.RegisterRowMapperFactory;

public class RegisterRowMapperFactoriesImpl extends SimpleExtensionConfigurer {

private final List<RowMapperFactory> rowMapperFactories;

public RegisterRowMapperFactoriesImpl(Annotation annotation) {
final RegisterRowMapperFactories registerRowMapperFactories = (RegisterRowMapperFactories) annotation;
this.rowMapperFactories = new ArrayList<>(registerRowMapperFactories.value().length);

for (RegisterRowMapperFactory registerRowMapperFactory : registerRowMapperFactories.value()) {
final Class<? extends RowMapperFactory> klass = registerRowMapperFactory.value();

try {
rowMapperFactories.add(klass.getConstructor().newInstance());
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate row mapper factory class " + klass, e);
}
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
ExtensionConfigurer delegate = new RegisterRowMapperFactoryImpl();

RegisterRowMapperFactories registerRowMapperFactories = (RegisterRowMapperFactories) annotation;
Stream.of(registerRowMapperFactories.value()).forEach(anno -> delegate.configureForType(config, anno, sqlObjectType));
RowMappers rowMappers = config.get(RowMappers.class);
rowMapperFactories.forEach(rowMappers::register);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,27 @@

import org.jdbi.v3.core.config.ConfigRegistry;
import org.jdbi.v3.core.extension.SimpleExtensionConfigurer;
import org.jdbi.v3.core.mapper.RowMapperFactory;
import org.jdbi.v3.core.mapper.RowMappers;
import org.jdbi.v3.sqlobject.config.RegisterRowMapperFactory;

public class RegisterRowMapperFactoryImpl extends SimpleExtensionConfigurer {
private final RowMapperFactory rowMapperFactory;

public RegisterRowMapperFactoryImpl(Annotation annotation) {
final RegisterRowMapperFactory registerRowMapperFactory = (RegisterRowMapperFactory) annotation;
final Class<? extends RowMapperFactory> klass = registerRowMapperFactory.value();

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
RegisterRowMapperFactory registerRowMapperFactory = (RegisterRowMapperFactory) annotation;
RowMappers mappers = config.get(RowMappers.class);
try {
mappers.register(registerRowMapperFactory.value().getConstructor().newInstance());
this.rowMapperFactory = klass.getConstructor().newInstance();
} catch (ReflectiveOperationException | SecurityException e) {
throw new IllegalStateException("Unable to instantiate row mapper factory class " + registerRowMapperFactory.value(), e);
throw new IllegalStateException("Unable to instantiate row mapper factory class " + klass, e);
}
}

@Override
public void configure(ConfigRegistry config, Annotation annotation, Class<?> sqlObjectType) {
RowMappers rowMappers = config.get(RowMappers.class);
rowMappers.register(rowMapperFactory);
}
}
Loading

0 comments on commit c247ce5

Please sign in to comment.