DATACMNS-637 - Performance improvements.
Made ObjectInstantiator interface public as otherwise the generated class to implement it cannot access it and thus the usage of the ByteCodeGeneratingEntityInstantiator fails completely. PreferredConstructor.isEnclosingClassParameter(…) now eagerly returns if the parameter itself is not an enclosing one and thus avoids a collection lookup and equals check. Moved equals check for the type to the very end of the equals check to increase the chances that other inequality guards kick in earlier. AbstractMappingContext now leaves the non-null-check for getPersistentEntity(…) to the factory method of ClassTypeInformation. We now pre-calculate the hash codes for TypeInformation implementations as far as possible as the instances are used as cache keys quite a lot. The same applies to AbstractPersistentProperty. BasicPersistentEntity now uses an ArrayList we sort during the verify() phase to mimic the previous behavior wich was implemented using a TreeSet as ArrayLists are way more performant when iterating over all elements which doWithProperties(…) is doing which is used quite a lot. BeanWrapper now avoids the getter lookup if field access is used. SimpleTypeHolder now uses a CopyOnWriteArrySet to leniently add types detected to be simple to the set of simple types to avoid ongoing checks against the inheritance hierarchy.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -168,11 +168,11 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
|
||||
|
||||
Assert.notNull(parameter);
|
||||
|
||||
if (parameters.isEmpty()) {
|
||||
if (parameters.isEmpty() || !parameter.isEnclosingClassParameter()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parameters.get(0).equals(parameter) && parameter.isEnclosingClassParameter();
|
||||
return parameters.get(0).equals(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,10 +312,10 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
|
||||
|
||||
boolean nameEquals = this.name == null ? that.name == null : this.name.equals(that.name);
|
||||
boolean keyEquals = this.key == null ? that.key == null : this.key.equals(that.key);
|
||||
boolean typeEquals = nullSafeEquals(this.type, that.type);
|
||||
boolean entityEquals = this.entity == null ? that.entity == null : this.entity.equals(that.entity);
|
||||
|
||||
return nameEquals && keyEquals && typeEquals && entityEquals;
|
||||
// Explicitly delay equals check on type as it might be expensive
|
||||
return nameEquals && keyEquals && entityEquals && this.type.equals(that.type);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -329,8 +329,8 @@ public class PreferredConstructor<T, P extends PersistentProperty<P>> {
|
||||
|
||||
result += 31 * nullSafeHashCode(this.name);
|
||||
result += 31 * nullSafeHashCode(this.key);
|
||||
result += 31 * nullSafeHashCode(this.type);
|
||||
result += 31 * nullSafeHashCode(this.entity);
|
||||
result += 31 * this.type.hashCode();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 by the original author(s).
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -137,7 +137,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
* @see org.springframework.data.mapping.model.MappingContext#getPersistentEntity(java.lang.Class)
|
||||
*/
|
||||
public E getPersistentEntity(Class<?> type) {
|
||||
Assert.notNull(type);
|
||||
return getPersistentEntity(ClassTypeInformation.from(type));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -53,6 +53,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
protected final Association<P> association;
|
||||
protected final PersistentEntity<?, P> owner;
|
||||
private final SimpleTypeHolder simpleTypeHolder;
|
||||
private final int hashCode;
|
||||
|
||||
public AbstractPersistentProperty(Field field, PropertyDescriptor propertyDescriptor, PersistentEntity<?, P> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
@@ -68,6 +69,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
this.association = isAssociation() ? createAssociation() : null;
|
||||
this.owner = owner;
|
||||
this.simpleTypeHolder = simpleTypeHolder;
|
||||
this.hashCode = this.field == null ? this.propertyDescriptor.hashCode() : this.field.hashCode();
|
||||
}
|
||||
|
||||
protected abstract Association<P> createAssociation();
|
||||
@@ -340,7 +342,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.field == null ? this.propertyDescriptor.hashCode() : this.field.hashCode();
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 by the original author(s).
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,12 @@ package org.springframework.data.mapping.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
@@ -52,7 +55,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
|
||||
private final PreferredConstructor<T, P> constructor;
|
||||
private final TypeInformation<T> information;
|
||||
private final Set<P> properties;
|
||||
private final List<P> properties;
|
||||
private final Comparator<P> comparator;
|
||||
private final Set<Association<P>> associations;
|
||||
|
||||
private final Map<String, P> propertyCache;
|
||||
@@ -83,7 +87,8 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
Assert.notNull(information);
|
||||
|
||||
this.information = information;
|
||||
this.properties = comparator == null ? new HashSet<P>() : new TreeSet<P>(comparator);
|
||||
this.properties = new ArrayList<P>();
|
||||
this.comparator = comparator;
|
||||
this.constructor = new PreferredConstructorDiscoverer<T, P>(information, this).getConstructor();
|
||||
this.associations = comparator == null ? new HashSet<Association<P>>() : new TreeSet<Association<P>>(
|
||||
new AssociationComparator<P>(comparator));
|
||||
@@ -171,6 +176,11 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
public void addPersistentProperty(P property) {
|
||||
|
||||
Assert.notNull(property);
|
||||
|
||||
if (properties.contains(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
properties.add(property);
|
||||
|
||||
if (!propertyCache.containsKey(property.getName())) {
|
||||
@@ -219,7 +229,10 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
* @see org.springframework.data.mapping.MutablePersistentEntity#addAssociation(org.springframework.data.mapping.model.Association)
|
||||
*/
|
||||
public void addAssociation(Association<P> association) {
|
||||
associations.add(association);
|
||||
|
||||
if (!associations.contains(association)) {
|
||||
associations.add(association);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -363,7 +376,12 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.MutablePersistentEntity#verify()
|
||||
*/
|
||||
public void verify() {}
|
||||
public void verify() {
|
||||
|
||||
if (comparator != null) {
|
||||
Collections.sort(properties, comparator);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 by the original author(s).
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -110,15 +110,16 @@ public class BeanWrapper<T> implements PersistentPropertyAccessor {
|
||||
|
||||
try {
|
||||
|
||||
Method getter = property.getGetter();
|
||||
|
||||
if (!property.usePropertyAccess()) {
|
||||
|
||||
Field field = property.getField();
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return (S) ReflectionUtils.getField(field, bean);
|
||||
}
|
||||
|
||||
} else if (property.usePropertyAccess() && getter != null) {
|
||||
Method getter = property.getGetter();
|
||||
|
||||
if (property.usePropertyAccess() && getter != null) {
|
||||
|
||||
ReflectionUtils.makeAccessible(getter);
|
||||
return (S) ReflectionUtils.invokeMethod(getter, bean);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -86,7 +87,7 @@ public class SimpleTypeHolder {
|
||||
public SimpleTypeHolder(Set<? extends Class<?>> customSimpleTypes, boolean registerDefaults) {
|
||||
|
||||
Assert.notNull(customSimpleTypes);
|
||||
this.simpleTypes = new HashSet<Class<?>>(customSimpleTypes);
|
||||
this.simpleTypes = new CopyOnWriteArraySet<Class<?>>(customSimpleTypes);
|
||||
|
||||
if (registerDefaults) {
|
||||
this.simpleTypes.addAll(DEFAULTS);
|
||||
@@ -104,7 +105,7 @@ public class SimpleTypeHolder {
|
||||
Assert.notNull(customSimpleTypes);
|
||||
Assert.notNull(source);
|
||||
|
||||
this.simpleTypes = new HashSet<Class<?>>(customSimpleTypes);
|
||||
this.simpleTypes = new CopyOnWriteArraySet<Class<?>>(customSimpleTypes);
|
||||
this.simpleTypes.addAll(source.simpleTypes);
|
||||
}
|
||||
|
||||
@@ -118,12 +119,13 @@ public class SimpleTypeHolder {
|
||||
|
||||
Assert.notNull(type);
|
||||
|
||||
if (Object.class.equals(type)) {
|
||||
if (Object.class.equals(type) || simpleTypes.contains(type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Class<?> clazz : simpleTypes) {
|
||||
if (clazz.isAssignableFrom(type)) {
|
||||
simpleTypes.add(type);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user