DATACMNS-809 - Refactor BasicPersistentEntity to set PersistentPropertyAccessorFactory.
PersistentPropertyAccessorFactory can be set on a BasicPersistentEntity. This is done by AbstractMappingContext once the entity is verified. This change reduces the count of PersistentPropertyAccessorFactory instances and performs the isSupported check only once, when initializing the entity. Original pull request: #159.
This commit is contained in:
committed by
Oliver Gierke
parent
41fe89743b
commit
defc3c7874
@@ -37,6 +37,7 @@ import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.mapping.model.DefaultPersistentPropertyAccessorFactory;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.MutablePersistentEntity;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
@@ -54,7 +55,7 @@ import org.springframework.util.StringUtils;
|
||||
* <p>
|
||||
* The implementation uses a {@link ReentrantReadWriteLock} to make sure {@link PersistentEntity} are completely
|
||||
* populated before accessing them from outside.
|
||||
*
|
||||
*
|
||||
* @param E the concrete {@link PersistentEntity} type the {@link MappingContext} implementation creates
|
||||
* @param P the concrete {@link PersistentProperty} type the {@link MappingContext} implementation creates
|
||||
* @author Jon Brisbin
|
||||
@@ -62,11 +63,13 @@ import org.springframework.util.StringUtils;
|
||||
* @author Michael Hunger
|
||||
* @author Thomas Darimont
|
||||
* @author Tomasz Wysocki
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>>
|
||||
implements MappingContext<E, P>, ApplicationEventPublisherAware, InitializingBean {
|
||||
|
||||
private final Map<TypeInformation<?>, E> persistentEntities = new HashMap<TypeInformation<?>, E>();
|
||||
private final DefaultPersistentPropertyAccessorFactory persistentPropertyAccessorFactory = new DefaultPersistentPropertyAccessorFactory();
|
||||
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@@ -78,7 +81,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
private final Lock read = lock.readLock();
|
||||
private final Lock write = lock.writeLock();
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)
|
||||
*/
|
||||
@@ -88,7 +91,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Sets the {@link Set} of types to populate the context initially.
|
||||
*
|
||||
*
|
||||
* @param initialEntitySet
|
||||
*/
|
||||
public void setInitialEntitySet(Set<? extends Class<?>> initialEntitySet) {
|
||||
@@ -100,7 +103,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
* {@link MappingException}s in case one tries to lookup a {@link PersistentEntity} not already in the context. This
|
||||
* defaults to {@literal false} so that unknown types will be transparently added to the MappingContext if not known
|
||||
* in advance.
|
||||
*
|
||||
*
|
||||
* @param strict
|
||||
*/
|
||||
public void setStrict(boolean strict) {
|
||||
@@ -111,7 +114,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
* Configures the {@link SimpleTypeHolder} to be used by the {@link MappingContext}. Allows customization of what
|
||||
* types will be regarded as simple types and thus not recursively analysed. Setting this to {@literal null} will
|
||||
* reset the context to use the default {@link SimpleTypeHolder}.
|
||||
*
|
||||
*
|
||||
* @param simpleTypes
|
||||
*/
|
||||
public void setSimpleTypeHolder(SimpleTypeHolder simpleTypes) {
|
||||
@@ -139,7 +142,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
return getPersistentEntity(ClassTypeInformation.from(type));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.MappingContext#hasPersistentEntityFor(java.lang.Class)
|
||||
*/
|
||||
@@ -216,7 +219,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
return getPersistentPropertyPath(propertyPath, ClassTypeInformation.from(type));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.MappingContext#getPersistentPropertyPath(org.springframework.data.mapping.context.InvalidPersistentPropertyPath)
|
||||
*/
|
||||
@@ -231,7 +234,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Creates a {@link PersistentPropertyPath} for the given parts and {@link TypeInformation}.
|
||||
*
|
||||
*
|
||||
* @param parts must not be {@literal null} or empty.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
@@ -268,7 +271,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Adds the given type to the {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
@@ -278,7 +281,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Adds the given {@link TypeInformation} to the {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param typeInformation
|
||||
* @return
|
||||
*/
|
||||
@@ -316,6 +319,9 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
entity.verify();
|
||||
|
||||
if (persistentPropertyAccessorFactory.isSupported(entity)) {
|
||||
entity.setPersistentPropertyAccessorFactory(persistentPropertyAccessorFactory);
|
||||
}
|
||||
} catch (MappingException e) {
|
||||
persistentEntities.remove(typeInformation);
|
||||
throw e;
|
||||
@@ -335,7 +341,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.context.PersistentEntityAware#getManagedTypes()
|
||||
*/
|
||||
@@ -354,7 +360,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Creates the concrete {@link PersistentEntity} instance.
|
||||
*
|
||||
*
|
||||
* @param <T>
|
||||
* @param typeInformation
|
||||
* @return
|
||||
@@ -363,7 +369,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Creates the concrete instance of {@link PersistentProperty}.
|
||||
*
|
||||
*
|
||||
* @param field
|
||||
* @param descriptor
|
||||
* @param owner
|
||||
@@ -373,7 +379,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
protected abstract P createPersistentProperty(Field field, PropertyDescriptor descriptor, E owner,
|
||||
SimpleTypeHolder simpleTypeHolder);
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@@ -398,7 +404,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
* default this will reject this for all types considered simple, but it might be necessary to tweak that in case you
|
||||
* have registered custom converters for top level types (which renders them to be considered simple) but still need
|
||||
* meta-information about them.
|
||||
*
|
||||
*
|
||||
* @param type will never be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -408,7 +414,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* {@link FieldCallback} to create {@link PersistentProperty} instances.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private final class PersistentPropertyCreator implements FieldCallback {
|
||||
@@ -420,7 +426,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Creates a new {@link PersistentPropertyCreator} for the given {@link PersistentEntity} and
|
||||
* {@link PropertyDescriptor}s.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param descriptors must not be {@literal null}.
|
||||
*/
|
||||
@@ -451,7 +457,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Adds {@link PersistentProperty} instances for all suitable {@link PropertyDescriptor}s without a backing
|
||||
* {@link Field}.
|
||||
*
|
||||
*
|
||||
* @see PersistentPropertyFilter
|
||||
*/
|
||||
public void addPropertiesForRemainingDescriptors() {
|
||||
@@ -494,7 +500,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Filter rejecting static fields as well as artifically introduced ones. See
|
||||
* {@link PersistentPropertyFilter#UNMAPPED_PROPERTIES} for details.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
static enum PersistentPropertyFilter implements FieldFilter {
|
||||
@@ -513,7 +519,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
UNMAPPED_PROPERTIES = Collections.unmodifiableCollection(matches);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.util.ReflectionUtils.FieldFilter#matches(java.lang.reflect.Field)
|
||||
*/
|
||||
@@ -534,7 +540,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link PropertyDescriptor} is one to create a {@link PersistentProperty} for.
|
||||
*
|
||||
*
|
||||
* @param descriptor must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@@ -557,7 +563,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Value object to help defining property exclusion based on name patterns and types.
|
||||
*
|
||||
*
|
||||
* @since 1.4
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@@ -569,7 +575,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
/**
|
||||
* Creates a new {@link PropertyMatch} for the given name pattern and type name. At least one of the paramters
|
||||
* must not be {@literal null}.
|
||||
*
|
||||
*
|
||||
* @param namePattern a regex pattern to match field names, can be {@literal null}.
|
||||
* @param typeName the name of the type to exclude, can be {@literal null}.
|
||||
*/
|
||||
@@ -583,7 +589,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
/**
|
||||
* Returns whether the given {@link Field} matches the defined {@link PropertyMatch}.
|
||||
*
|
||||
*
|
||||
* @param field must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -66,11 +66,12 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
|
||||
private final Map<String, P> propertyCache;
|
||||
private final Map<Class<? extends Annotation>, Annotation> annotationCache;
|
||||
private final PersistentPropertyAccessorFactory propertyAccessorFactory;
|
||||
|
||||
private P idProperty;
|
||||
private P versionProperty;
|
||||
|
||||
private PersistentPropertyAccessorFactory propertyAccessorFactory;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
|
||||
*
|
||||
@@ -101,7 +102,6 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
|
||||
this.propertyCache = new HashMap<String, P>();
|
||||
this.annotationCache = new HashMap<Class<? extends Annotation>, Annotation>();
|
||||
this.propertyAccessorFactory = new DefaultPersistentPropertyAccessorFactory();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -391,16 +391,32 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.MutablePersistentEntity#setPersistentPropertyAccessorFactory(org.springframework.data.mapping.model.PersistentPropertyAccessorFactory)
|
||||
*/
|
||||
@Override
|
||||
public void setPersistentPropertyAccessorFactory(PersistentPropertyAccessorFactory factory) {
|
||||
this.propertyAccessorFactory = factory;
|
||||
}
|
||||
|
||||
public PersistentPropertyAccessorFactory getPropertyAccessorFactory() {
|
||||
return propertyAccessorFactory;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public PersistentPropertyAccessor getPropertyAccessor(Object bean) {
|
||||
|
||||
Assert.notNull(bean, "Target bean must not be null!");
|
||||
Assert.isTrue(getType().isInstance(bean), "Target bean is not of type of the persistent entity!");
|
||||
|
||||
if (propertyAccessorFactory == null) {
|
||||
return new BeanWrapper<Object>(bean);
|
||||
}
|
||||
|
||||
return propertyAccessorFactory.getPropertyAccessor(this, bean);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.SimpleAssociationHandler;
|
||||
import org.springframework.data.mapping.SimplePropertyHandler;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -85,6 +86,16 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#isSupported(org.springframework.data.mapping.PersistentEntity)
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported(PersistentEntity<?, ?> entity) {
|
||||
|
||||
Assert.notNull(entity, "PersistentEntity must not be null!");
|
||||
return canGenerateAccessorClass(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an accessor class can be generated.
|
||||
*
|
||||
|
||||
@@ -21,7 +21,7 @@ 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
|
||||
* @author Oliver Gierke
|
||||
* @since 1.13
|
||||
@@ -37,7 +37,13 @@ public class DefaultPersistentPropertyAccessorFactory implements PersistentPrope
|
||||
@Override
|
||||
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
|
||||
|
||||
return ClassGeneratingPropertyAccessorFactory.canGenerateAccessorClass(entity)
|
||||
? classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean) : new BeanWrapper<Object>(bean);
|
||||
return classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#isSupported(org.springframework.data.mapping.PersistentEntity)
|
||||
*/
|
||||
public boolean isSupported(PersistentEntity<?, ?> entity) {
|
||||
return classGeneratingPropertyAccessorFactory.isSupported(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
* Copyright (c) 2011-2016 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.
|
||||
@@ -18,24 +18,26 @@ package org.springframework.data.mapping.model;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
|
||||
/**
|
||||
* Interface capturing mutator methods for {@link PersistentEntity}s.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface MutablePersistentEntity<T, P extends PersistentProperty<P>> extends PersistentEntity<T, P> {
|
||||
|
||||
/**
|
||||
* Adds a {@link PersistentProperty} to the entity.
|
||||
*
|
||||
*
|
||||
* @param property
|
||||
*/
|
||||
void addPersistentProperty(P property);
|
||||
|
||||
/**
|
||||
* Adds an {@link Association} to the entity.
|
||||
*
|
||||
*
|
||||
* @param association
|
||||
*/
|
||||
void addAssociation(Association<P> association);
|
||||
@@ -43,8 +45,16 @@ public interface MutablePersistentEntity<T, P extends PersistentProperty<P>> ext
|
||||
/**
|
||||
* Callback method to trigger validation of the {@link PersistentEntity}. As {@link MutablePersistentEntity} is not
|
||||
* immutable there might be some verification steps necessary after the object has reached is final state.
|
||||
*
|
||||
*
|
||||
* @throws MappingException in case the entity is invalid
|
||||
*/
|
||||
void verify() throws MappingException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link PersistentPropertyAccessorFactory} for the entity. A {@link PersistentPropertyAccessorFactory}
|
||||
* creates {@link PersistentPropertyAccessor}s for instances of this entity.
|
||||
*
|
||||
* @param factory
|
||||
*/
|
||||
void setPersistentPropertyAccessorFactory(PersistentPropertyAccessorFactory factory);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
|
||||
/**
|
||||
* Factory to create {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and bean instance.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Oliver Gierke
|
||||
* @since 1.13
|
||||
@@ -29,10 +29,18 @@ public interface PersistentPropertyAccessorFactory {
|
||||
|
||||
/**
|
||||
* Returns a {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param bean must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean);
|
||||
|
||||
/**
|
||||
* Returns whether given {@link PersistentEntity} is supported by this {@link PersistentPropertyAccessorFactory}.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
boolean isSupported(PersistentEntity<?, ?> entity);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user