From aa4c51e1ea619decd7d1471c50e72a365f1d8626 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Feb 2017 08:28:41 +0100 Subject: [PATCH] DATACMNS-867 - Cache constructors in ClassGeneratingPropertyAccesssorFactory. Fix hotspot in constructor lookup - in particular the propertyAccessorClass.getConstructors() call. Additionally fix another minor issue in assertion message creation. --- .../mapping/model/BasicPersistentEntity.java | 4 +- ...lassGeneratingPropertyAccessorFactory.java | 38 ++++++++----------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index 3e433270a..def7da1b7 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -436,8 +436,8 @@ public class BasicPersistentEntity> implement public PersistentPropertyAccessor getPropertyAccessor(Object bean) { Assert.notNull(bean, "Target bean must not be null!"); - Assert.isTrue(getType().isInstance(bean), - () -> String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName())); + Assert.isTrue(getType().isInstance(bean), () -> + String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName())); return propertyAccessorFactory.getPropertyAccessor(this, bean); } diff --git a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java index f5d9ddbc7..7cb87a325 100644 --- a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java +++ b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-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. @@ -21,6 +21,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.experimental.UtilityClass; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; @@ -60,12 +61,14 @@ import org.springframework.util.ReflectionUtils; * * @author Mark Paluch * @author Oliver Gierke + * @author Christoph Strobl * @since 1.13 */ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccessorFactory { private volatile Map, Class> propertyAccessorClasses = new HashMap, Class>( 32); + private volatile Map, Constructor> constructorMap = new HashMap<>(32); /* * (non-Javadoc) @@ -74,14 +77,13 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert @Override public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity entity, Object bean) { - Class propertyAccessorClass = propertyAccessorClasses.get(entity.getTypeInformation()); - - if (propertyAccessorClass == null) { - propertyAccessorClass = potentiallyCreateAndRegisterPersistentPropertyAccessorClass(entity); - } + final Class propertyAccessorClass = propertyAccessorClasses.computeIfAbsent( + entity.getTypeInformation(), k -> potentiallyCreateAndRegisterPersistentPropertyAccessorClass(entity)); try { - return (PersistentPropertyAccessor) propertyAccessorClass.getConstructors()[0].newInstance(bean); + + return (PersistentPropertyAccessor) constructorMap + .computeIfAbsent(propertyAccessorClass, k -> propertyAccessorClass.getConstructors()[0]).newInstance(bean); } catch (Exception e) { throw new IllegalArgumentException(String.format("Cannot create persistent property accessor for %s", entity), e); } @@ -107,26 +109,18 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert final Set hashCodes = new HashSet<>(); final AtomicInteger propertyCount = new AtomicInteger(); - entity.doWithProperties(new SimplePropertyHandler() { + entity.doWithProperties((SimplePropertyHandler) property -> { - @Override - public void doWithPersistentProperty(PersistentProperty property) { - - hashCodes.add(property.getName().hashCode()); - propertyCount.incrementAndGet(); - } + hashCodes.add(property.getName().hashCode()); + propertyCount.incrementAndGet(); }); - entity.doWithAssociations(new SimpleAssociationHandler() { + entity.doWithAssociations((SimpleAssociationHandler) association -> { - @Override - public void doWithAssociation(Association> association) { + if (association.getInverse() != null) { - if (association.getInverse() != null) { - - hashCodes.add(association.getInverse().getName().hashCode()); - propertyCount.incrementAndGet(); - } + hashCodes.add(association.getInverse().getName().hashCode()); + propertyCount.incrementAndGet(); } });