Skip to content

Commit 1075a25

Browse files
mp911dechristophstrobl
authored andcommitted
Revisit internal caching arrangements.
Introduce caching and reduce allocations on hot code paths. Closes: #4818 Original Pull Request: #4819
1 parent 5419414 commit 1075a25

File tree

4 files changed

+62
-20
lines changed

4 files changed

+62
-20
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultMongoTypeMapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ public DocumentTypeAliasAccessor(@Nullable String typeKey) {
171171
this.typeKey = typeKey;
172172
}
173173

174+
@Override
174175
public Alias readAliasFrom(Bson source) {
175176

176177
if (source instanceof List) {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Map;
2828
import java.util.Optional;
2929
import java.util.Set;
30+
import java.util.function.BiPredicate;
3031
import java.util.function.Predicate;
3132
import java.util.stream.Collectors;
3233

@@ -130,6 +131,23 @@ public class MappingMongoConverter extends AbstractMongoConverter
130131
private static final String INCOMPATIBLE_TYPES = "Cannot convert %1$s of type %2$s into an instance of %3$s; Implement a custom Converter<%2$s, %3$s> and register it with the CustomConversions; Parent object was: %4$s";
131132
private static final String INVALID_TYPE_TO_READ = "Expected to read Document %s into type %s but didn't find a PersistentEntity for the latter";
132133

134+
private static final BiPredicate<MongoPersistentEntity<?>, MongoPersistentProperty> PROPERTY_FILTER = (e,
135+
property) -> {
136+
137+
if (property.isIdProperty()) {
138+
return false;
139+
}
140+
141+
if (e.isCreatorArgument(property)) {
142+
return false;
143+
}
144+
145+
if (!property.isReadable()) {
146+
return false;
147+
}
148+
return true;
149+
};
150+
133151
public static final TypeInformation<Bson> BSON = TypeInformation.of(Bson.class);
134152

135153
protected static final Log LOGGER = LogFactory.getLog(MappingMongoConverter.class);
@@ -368,7 +386,7 @@ private <R> R doReadProjection(ConversionContext context, Bson bson, EntityProje
368386
evaluator, spELContext);
369387

370388
readProperties(context, entity, convertingAccessor, documentAccessor, valueProvider, evaluator,
371-
Predicates.isTrue());
389+
(mongoPersistentProperties, mongoPersistentProperty) -> true);
372390
return (R) projectionFactory.createProjection(mappedType.getType(), accessor.getBean());
373391
}
374392

@@ -518,26 +536,42 @@ private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(Con
518536
parameterProvider);
519537
}
520538

539+
class EvaluatingDocumentAccessor extends DocumentAccessor implements ValueExpressionEvaluator {
540+
541+
/**
542+
* Creates a new {@link DocumentAccessor} for the given {@link Document}.
543+
*
544+
* @param document must be a {@link Document} effectively, must not be {@literal null}.
545+
*/
546+
public EvaluatingDocumentAccessor(Bson document) {
547+
super(document);
548+
}
549+
550+
@Override
551+
public <T> T evaluate(String expression) {
552+
return expressionEvaluatorFactory.create(getDocument()).evaluate(expression);
553+
}
554+
}
555+
521556
private <S> S read(ConversionContext context, MongoPersistentEntity<S> entity, Document bson) {
522557

523558
S existing = context.findContextualEntity(entity, bson);
524559
if (existing != null) {
525560
return existing;
526561
}
527562

528-
ValueExpressionEvaluator evaluator = expressionEvaluatorFactory.create(bson);
529-
DocumentAccessor documentAccessor = new DocumentAccessor(bson);
530-
563+
EvaluatingDocumentAccessor documentAccessor = new EvaluatingDocumentAccessor(bson);
531564
InstanceCreatorMetadata<MongoPersistentProperty> instanceCreatorMetadata = entity.getInstanceCreatorMetadata();
532565

533566
ParameterValueProvider<MongoPersistentProperty> provider = instanceCreatorMetadata != null
534-
&& instanceCreatorMetadata.hasParameters() ? getParameterProvider(context, entity, documentAccessor, evaluator)
567+
&& instanceCreatorMetadata.hasParameters()
568+
? getParameterProvider(context, entity, documentAccessor, documentAccessor)
535569
: NoOpParameterValueProvider.INSTANCE;
536570

537571
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
538572
S instance = instantiator.createInstance(entity, provider);
539573

540-
return populateProperties(context, entity, documentAccessor, evaluator, instance);
574+
return populateProperties(context, entity, documentAccessor, documentAccessor, instance);
541575
}
542576

543577
private <S> S populateProperties(ConversionContext context, MongoPersistentEntity<S> entity,
@@ -559,9 +593,7 @@ private <S> S populateProperties(ConversionContext context, MongoPersistentEntit
559593
MongoDbPropertyValueProvider valueProvider = new MongoDbPropertyValueProvider(contextToUse, documentAccessor,
560594
evaluator, spELContext);
561595

562-
Predicate<MongoPersistentProperty> propertyFilter = isIdentifier(entity).or(isConstructorArgument(entity))
563-
.or(Predicates.negate(PersistentProperty::isReadable)).negate();
564-
readProperties(contextToUse, entity, accessor, documentAccessor, valueProvider, evaluator, propertyFilter);
596+
readProperties(contextToUse, entity, accessor, documentAccessor, valueProvider, evaluator, PROPERTY_FILTER);
565597

566598
return accessor.getBean();
567599
}
@@ -606,13 +638,13 @@ private Object readIdValue(ConversionContext context, ValueExpressionEvaluator e
606638
private void readProperties(ConversionContext context, MongoPersistentEntity<?> entity,
607639
PersistentPropertyAccessor<?> accessor, DocumentAccessor documentAccessor,
608640
MongoDbPropertyValueProvider valueProvider, ValueExpressionEvaluator evaluator,
609-
Predicate<MongoPersistentProperty> propertyFilter) {
641+
BiPredicate<MongoPersistentEntity<?>, MongoPersistentProperty> propertyFilter) {
610642

611643
DbRefResolverCallback callback = null;
612644

613645
for (MongoPersistentProperty prop : entity) {
614646

615-
if (!propertyFilter.test(prop)) {
647+
if (!propertyFilter.test(entity, prop)) {
616648
continue;
617649
}
618650

@@ -1943,10 +1975,6 @@ static class MongoDbPropertyValueProvider implements PropertyValueProvider<Mongo
19431975
MongoDbPropertyValueProvider(ConversionContext context, DocumentAccessor accessor,
19441976
ValueExpressionEvaluator evaluator, SpELContext spELContext) {
19451977

1946-
Assert.notNull(context, "ConversionContext must no be null");
1947-
Assert.notNull(accessor, "DocumentAccessor must no be null");
1948-
Assert.notNull(evaluator, "ValueExpressionEvaluator must not be null");
1949-
19501978
this.context = context;
19511979
this.accessor = accessor;
19521980
this.evaluator = evaluator;
@@ -2359,9 +2387,6 @@ protected static class DefaultConversionContext implements ConversionContext {
23592387
public <S extends Object> S convert(Object source, TypeInformation<? extends S> typeHint,
23602388
ConversionContext context) {
23612389

2362-
Assert.notNull(source, "Source must not be null");
2363-
Assert.notNull(typeHint, "TypeInformation must not be null");
2364-
23652390
if (conversions.hasCustomReadTarget(source.getClass(), typeHint.getType())) {
23662391
return (S) elementConverter.convert(source, typeHint);
23672392
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/CachingMongoPersistentProperty.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
*/
3131
public class CachingMongoPersistentProperty extends BasicMongoPersistentProperty {
3232

33+
private final Lazy<Boolean> isEntity = Lazy.of(super::isEntity);
34+
private final Lazy<Boolean> isUnwrapped = Lazy.of(super::isUnwrapped);
3335
private final Lazy<Boolean> isIdProperty = Lazy.of(super::isIdProperty);
3436
private final Lazy<Boolean> isAssociation = Lazy.of(super::isAssociation);
3537
private final Lazy<DBRef> dbref = Lazy.of(super::getDBRef);
@@ -58,6 +60,16 @@ public CachingMongoPersistentProperty(Property property, MongoPersistentEntity<?
5860
super(property, owner, simpleTypeHolder, fieldNamingStrategy);
5961
}
6062

63+
@Override
64+
public boolean isEntity() {
65+
return isEntity.get();
66+
}
67+
68+
@Override
69+
public boolean isUnwrapped() {
70+
return isUnwrapped.get();
71+
}
72+
6173
@Override
6274
public boolean isIdProperty() {
6375
return isIdProperty.get();

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/FieldName.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525
* @author Christoph Strobl
2626
* @since 4.2
2727
*/
28-
public record FieldName(String name, Type type) {
28+
public record FieldName(String name, Type type, String[] parts) {
29+
30+
public FieldName(String name, Type type) {
31+
this(name, type, name.split("\\."));
32+
}
2933

3034
private static final String ID_KEY = "_id";
3135

@@ -65,7 +69,7 @@ public String[] parts() {
6569
return new String[] { name };
6670
}
6771

68-
return name.split("\\.");
72+
return parts;
6973
}
7074

7175
/**

0 commit comments

Comments
 (0)