DATACMNS-809 - Add Class-generating property accessor factory.
We now support generated PersistentPropertyAccessors when using Java 7 and if property/association name hashCodes are unique within a PersistentEntity. Generated PersistentPropertyAccessors provide optimized access to properties. They use either MethodHandles or direct property/field access, depending on the visibility/final modifiers of the entity type and its members. A generated PersistentPropertyAccessor is injected into the originating class loader of the entity class to enable optimizations for package-default/protected member access. Original pull request: #159.
This commit is contained in:
committed by
Oliver Gierke
parent
0515b1308c
commit
899a98c83e
@@ -45,12 +45,13 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Simple value object to capture information of {@link PersistentEntity}s.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jon Brisbin
|
||||
* @author Patryk Wasik
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implements MutablePersistentEntity<T, P> {
|
||||
|
||||
@@ -66,9 +67,11 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
private P idProperty;
|
||||
private P versionProperty;
|
||||
|
||||
private final PersistentPropertyAccessorFactory propertyAccessorFactory;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
|
||||
*
|
||||
*
|
||||
* @param information must not be {@literal null}.
|
||||
*/
|
||||
public BasicPersistentEntity(TypeInformation<T> information) {
|
||||
@@ -79,7 +82,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
* Creates a new {@link BasicPersistentEntity} for the given {@link TypeInformation} and {@link Comparator}. The given
|
||||
* {@link Comparator} will be used to define the order of the {@link PersistentProperty} instances added to the
|
||||
* entity.
|
||||
*
|
||||
*
|
||||
* @param information must not be {@literal null}.
|
||||
* @param comparator can be {@literal null}.
|
||||
*/
|
||||
@@ -91,14 +94,15 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
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));
|
||||
this.associations = comparator == null ? new HashSet<Association<P>>()
|
||||
: new TreeSet<Association<P>>(new AssociationComparator<P>(comparator));
|
||||
|
||||
this.propertyCache = new HashMap<String, P>();
|
||||
this.annotationCache = new HashMap<Class<? extends Annotation>, Annotation>();
|
||||
this.propertyAccessorFactory = new DefaultPersistentPropertyAccessorFactory();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getPersistenceConstructor()
|
||||
*/
|
||||
@@ -122,7 +126,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return this.idProperty == null ? false : this.idProperty.equals(property);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#isVersionProperty(org.springframework.data.mapping.PersistentProperty)
|
||||
*/
|
||||
@@ -146,7 +150,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return idProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getVersionProperty()
|
||||
*/
|
||||
@@ -154,7 +158,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return versionProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#hasIdProperty()
|
||||
*/
|
||||
@@ -162,7 +166,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return idProperty != null;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#hasVersionProperty()
|
||||
*/
|
||||
@@ -170,7 +174,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return versionProperty != null;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.MutablePersistentEntity#addPersistentProperty(P)
|
||||
*/
|
||||
@@ -197,9 +201,11 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
if (property.isVersionProperty()) {
|
||||
|
||||
if (this.versionProperty != null) {
|
||||
throw new MappingException(String.format(
|
||||
"Attempt to add version property %s but already have property %s registered "
|
||||
+ "as version. Check your mapping configuration!", property.getField(), versionProperty.getField()));
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
"Attempt to add version property %s but already have property %s registered "
|
||||
+ "as version. Check your mapping configuration!",
|
||||
property.getField(), versionProperty.getField()));
|
||||
}
|
||||
|
||||
this.versionProperty = property;
|
||||
@@ -208,7 +214,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
|
||||
/**
|
||||
* Returns the given property if it is a better candidate for the id property than the current id property.
|
||||
*
|
||||
*
|
||||
* @param property the new id property candidate, will never be {@literal null}.
|
||||
* @return the given id property or {@literal null} if the given property is not an id property.
|
||||
*/
|
||||
@@ -244,7 +250,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return propertyCache.get(name);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.Class)
|
||||
*/
|
||||
@@ -279,7 +285,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return information.getType();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getTypeAlias()
|
||||
*/
|
||||
@@ -312,7 +318,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#doWithProperties(org.springframework.data.mapping.PropertyHandler.Simple)
|
||||
*/
|
||||
@@ -354,7 +360,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#findAnnotation(java.lang.Class)
|
||||
*/
|
||||
@@ -372,7 +378,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return annotation;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.MutablePersistentEntity#verify()
|
||||
*/
|
||||
@@ -383,7 +389,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
|
||||
*/
|
||||
@@ -393,10 +399,10 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
Assert.notNull(bean, "Target bean must not be null!");
|
||||
Assert.isTrue(getType().isInstance(bean), "Target bean is not of type of the persistent entity!");
|
||||
|
||||
return new BeanWrapper<Object>(bean);
|
||||
return propertyAccessorFactory.getPropertyAccessor(this, bean);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getIdentifierAccessor(java.lang.Object)
|
||||
*/
|
||||
@@ -419,7 +425,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier()
|
||||
*/
|
||||
@@ -431,11 +437,11 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
|
||||
/**
|
||||
* Simple {@link Comparator} adaptor to delegate ordering to the inverse properties of the association.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static final class AssociationComparator<P extends PersistentProperty<P>> implements
|
||||
Comparator<Association<P>>, Serializable {
|
||||
private static final class AssociationComparator<P extends PersistentProperty<P>>
|
||||
implements Comparator<Association<P>>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4508054194886854513L;
|
||||
private final Comparator<P> delegate;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link PersistentPropertyAccessorFactory}. Accessors can access bean properties either via
|
||||
* reflection or use generated classes with direct field/method access.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.13
|
||||
*/
|
||||
public class DefaultPersistentPropertyAccessorFactory implements PersistentPropertyAccessorFactory {
|
||||
|
||||
private final ClassGeneratingPropertyAccessorFactory classGeneratingPropertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory();
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
|
||||
|
||||
if (ClassGeneratingPropertyAccessorFactory.canGenerateAccessorClass(entity)) {
|
||||
return classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean);
|
||||
}
|
||||
return new BeanWrapper<Object>(bean);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
|
||||
/**
|
||||
* Factory to create {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.13
|
||||
*/
|
||||
public interface PersistentPropertyAccessorFactory {
|
||||
|
||||
/**
|
||||
* Returns a {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}.
|
||||
*
|
||||
* @param bean
|
||||
* @return
|
||||
*/
|
||||
PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user