Skip to content

Commit defc3c7

Browse files
mp911deodrotbohm
authored andcommitted
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.
1 parent 41fe897 commit defc3c7

8 files changed

+123
-42
lines changed

src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.data.mapping.PersistentEntity;
3838
import org.springframework.data.mapping.PersistentProperty;
3939
import org.springframework.data.mapping.PropertyPath;
40+
import org.springframework.data.mapping.model.DefaultPersistentPropertyAccessorFactory;
4041
import org.springframework.data.mapping.model.MappingException;
4142
import org.springframework.data.mapping.model.MutablePersistentEntity;
4243
import org.springframework.data.mapping.model.SimpleTypeHolder;
@@ -54,19 +55,21 @@
5455
* <p>
5556
* The implementation uses a {@link ReentrantReadWriteLock} to make sure {@link PersistentEntity} are completely
5657
* populated before accessing them from outside.
57-
*
58+
*
5859
* @param E the concrete {@link PersistentEntity} type the {@link MappingContext} implementation creates
5960
* @param P the concrete {@link PersistentProperty} type the {@link MappingContext} implementation creates
6061
* @author Jon Brisbin
6162
* @author Oliver Gierke
6263
* @author Michael Hunger
6364
* @author Thomas Darimont
6465
* @author Tomasz Wysocki
66+
* @author Mark Paluch
6567
*/
6668
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>>
6769
implements MappingContext<E, P>, ApplicationEventPublisherAware, InitializingBean {
6870

6971
private final Map<TypeInformation<?>, E> persistentEntities = new HashMap<TypeInformation<?>, E>();
72+
private final DefaultPersistentPropertyAccessorFactory persistentPropertyAccessorFactory = new DefaultPersistentPropertyAccessorFactory();
7073

7174
private ApplicationEventPublisher applicationEventPublisher;
7275

@@ -78,7 +81,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
7881
private final Lock read = lock.readLock();
7982
private final Lock write = lock.writeLock();
8083

81-
/*
84+
/*
8285
* (non-Javadoc)
8386
* @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)
8487
*/
@@ -88,7 +91,7 @@ public void setApplicationEventPublisher(ApplicationEventPublisher applicationEv
8891

8992
/**
9093
* Sets the {@link Set} of types to populate the context initially.
91-
*
94+
*
9295
* @param initialEntitySet
9396
*/
9497
public void setInitialEntitySet(Set<? extends Class<?>> initialEntitySet) {
@@ -100,7 +103,7 @@ public void setInitialEntitySet(Set<? extends Class<?>> initialEntitySet) {
100103
* {@link MappingException}s in case one tries to lookup a {@link PersistentEntity} not already in the context. This
101104
* defaults to {@literal false} so that unknown types will be transparently added to the MappingContext if not known
102105
* in advance.
103-
*
106+
*
104107
* @param strict
105108
*/
106109
public void setStrict(boolean strict) {
@@ -111,7 +114,7 @@ public void setStrict(boolean strict) {
111114
* Configures the {@link SimpleTypeHolder} to be used by the {@link MappingContext}. Allows customization of what
112115
* types will be regarded as simple types and thus not recursively analysed. Setting this to {@literal null} will
113116
* reset the context to use the default {@link SimpleTypeHolder}.
114-
*
117+
*
115118
* @param simpleTypes
116119
*/
117120
public void setSimpleTypeHolder(SimpleTypeHolder simpleTypes) {
@@ -139,7 +142,7 @@ public E getPersistentEntity(Class<?> type) {
139142
return getPersistentEntity(ClassTypeInformation.from(type));
140143
}
141144

142-
/*
145+
/*
143146
* (non-Javadoc)
144147
* @see org.springframework.data.mapping.context.MappingContext#hasPersistentEntityFor(java.lang.Class)
145148
*/
@@ -216,7 +219,7 @@ public PersistentPropertyPath<P> getPersistentPropertyPath(String propertyPath,
216219
return getPersistentPropertyPath(propertyPath, ClassTypeInformation.from(type));
217220
}
218221

219-
/*
222+
/*
220223
* (non-Javadoc)
221224
* @see org.springframework.data.mapping.context.MappingContext#getPersistentPropertyPath(org.springframework.data.mapping.context.InvalidPersistentPropertyPath)
222225
*/
@@ -231,7 +234,7 @@ private PersistentPropertyPath<P> getPersistentPropertyPath(String propertyPath,
231234

232235
/**
233236
* Creates a {@link PersistentPropertyPath} for the given parts and {@link TypeInformation}.
234-
*
237+
*
235238
* @param parts must not be {@literal null} or empty.
236239
* @param type must not be {@literal null}.
237240
* @return
@@ -268,7 +271,7 @@ private PersistentPropertyPath<P> getPersistentPropertyPath(Collection<String> p
268271

269272
/**
270273
* Adds the given type to the {@link MappingContext}.
271-
*
274+
*
272275
* @param type
273276
* @return
274277
*/
@@ -278,7 +281,7 @@ protected E addPersistentEntity(Class<?> type) {
278281

279282
/**
280283
* Adds the given {@link TypeInformation} to the {@link MappingContext}.
281-
*
284+
*
282285
* @param typeInformation
283286
* @return
284287
*/
@@ -316,6 +319,9 @@ protected E addPersistentEntity(TypeInformation<?> typeInformation) {
316319

317320
entity.verify();
318321

322+
if (persistentPropertyAccessorFactory.isSupported(entity)) {
323+
entity.setPersistentPropertyAccessorFactory(persistentPropertyAccessorFactory);
324+
}
319325
} catch (MappingException e) {
320326
persistentEntities.remove(typeInformation);
321327
throw e;
@@ -335,7 +341,7 @@ protected E addPersistentEntity(TypeInformation<?> typeInformation) {
335341
}
336342
}
337343

338-
/*
344+
/*
339345
* (non-Javadoc)
340346
* @see org.springframework.data.mapping.context.PersistentEntityAware#getManagedTypes()
341347
*/
@@ -354,7 +360,7 @@ public Collection<TypeInformation<?>> getManagedTypes() {
354360

355361
/**
356362
* Creates the concrete {@link PersistentEntity} instance.
357-
*
363+
*
358364
* @param <T>
359365
* @param typeInformation
360366
* @return
@@ -363,7 +369,7 @@ public Collection<TypeInformation<?>> getManagedTypes() {
363369

364370
/**
365371
* Creates the concrete instance of {@link PersistentProperty}.
366-
*
372+
*
367373
* @param field
368374
* @param descriptor
369375
* @param owner
@@ -373,7 +379,7 @@ public Collection<TypeInformation<?>> getManagedTypes() {
373379
protected abstract P createPersistentProperty(Field field, PropertyDescriptor descriptor, E owner,
374380
SimpleTypeHolder simpleTypeHolder);
375381

376-
/*
382+
/*
377383
* (non-Javadoc)
378384
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
379385
*/
@@ -398,7 +404,7 @@ public void initialize() {
398404
* default this will reject this for all types considered simple, but it might be necessary to tweak that in case you
399405
* have registered custom converters for top level types (which renders them to be considered simple) but still need
400406
* meta-information about them.
401-
*
407+
*
402408
* @param type will never be {@literal null}.
403409
* @return
404410
*/
@@ -408,7 +414,7 @@ protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
408414

409415
/**
410416
* {@link FieldCallback} to create {@link PersistentProperty} instances.
411-
*
417+
*
412418
* @author Oliver Gierke
413419
*/
414420
private final class PersistentPropertyCreator implements FieldCallback {
@@ -420,7 +426,7 @@ private final class PersistentPropertyCreator implements FieldCallback {
420426
/**
421427
* Creates a new {@link PersistentPropertyCreator} for the given {@link PersistentEntity} and
422428
* {@link PropertyDescriptor}s.
423-
*
429+
*
424430
* @param entity must not be {@literal null}.
425431
* @param descriptors must not be {@literal null}.
426432
*/
@@ -451,7 +457,7 @@ public void doWith(Field field) {
451457
/**
452458
* Adds {@link PersistentProperty} instances for all suitable {@link PropertyDescriptor}s without a backing
453459
* {@link Field}.
454-
*
460+
*
455461
* @see PersistentPropertyFilter
456462
*/
457463
public void addPropertiesForRemainingDescriptors() {
@@ -494,7 +500,7 @@ private void createAndRegisterProperty(Field field, PropertyDescriptor descripto
494500
/**
495501
* Filter rejecting static fields as well as artifically introduced ones. See
496502
* {@link PersistentPropertyFilter#UNMAPPED_PROPERTIES} for details.
497-
*
503+
*
498504
* @author Oliver Gierke
499505
*/
500506
static enum PersistentPropertyFilter implements FieldFilter {
@@ -513,7 +519,7 @@ static enum PersistentPropertyFilter implements FieldFilter {
513519
UNMAPPED_PROPERTIES = Collections.unmodifiableCollection(matches);
514520
}
515521

516-
/*
522+
/*
517523
* (non-Javadoc)
518524
* @see org.springframework.util.ReflectionUtils.FieldFilter#matches(java.lang.reflect.Field)
519525
*/
@@ -534,7 +540,7 @@ public boolean matches(Field field) {
534540

535541
/**
536542
* Returns whether the given {@link PropertyDescriptor} is one to create a {@link PersistentProperty} for.
537-
*
543+
*
538544
* @param descriptor must not be {@literal null}.
539545
* @return
540546
*/
@@ -557,7 +563,7 @@ public boolean matches(PropertyDescriptor descriptor) {
557563

558564
/**
559565
* Value object to help defining property exclusion based on name patterns and types.
560-
*
566+
*
561567
* @since 1.4
562568
* @author Oliver Gierke
563569
*/
@@ -569,7 +575,7 @@ static class PropertyMatch {
569575
/**
570576
* Creates a new {@link PropertyMatch} for the given name pattern and type name. At least one of the paramters
571577
* must not be {@literal null}.
572-
*
578+
*
573579
* @param namePattern a regex pattern to match field names, can be {@literal null}.
574580
* @param typeName the name of the type to exclude, can be {@literal null}.
575581
*/
@@ -583,7 +589,7 @@ public PropertyMatch(String namePattern, String typeName) {
583589

584590
/**
585591
* Returns whether the given {@link Field} matches the defined {@link PropertyMatch}.
586-
*
592+
*
587593
* @param field must not be {@literal null}.
588594
* @return
589595
*/

src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
6666

6767
private final Map<String, P> propertyCache;
6868
private final Map<Class<? extends Annotation>, Annotation> annotationCache;
69-
private final PersistentPropertyAccessorFactory propertyAccessorFactory;
7069

7170
private P idProperty;
7271
private P versionProperty;
7372

73+
private PersistentPropertyAccessorFactory propertyAccessorFactory;
74+
7475
/**
7576
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
7677
*
@@ -101,7 +102,6 @@ public BasicPersistentEntity(TypeInformation<T> information, Comparator<P> compa
101102

102103
this.propertyCache = new HashMap<String, P>();
103104
this.annotationCache = new HashMap<Class<? extends Annotation>, Annotation>();
104-
this.propertyAccessorFactory = new DefaultPersistentPropertyAccessorFactory();
105105
}
106106

107107
/*
@@ -391,16 +391,32 @@ public void verify() {
391391
}
392392
}
393393

394-
/*
395-
* (non-Javadoc)
396-
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
394+
/* (non-Javadoc)
395+
* @see org.springframework.data.mapping.model.MutablePersistentEntity#setPersistentPropertyAccessorFactory(org.springframework.data.mapping.model.PersistentPropertyAccessorFactory)
397396
*/
398397
@Override
398+
public void setPersistentPropertyAccessorFactory(PersistentPropertyAccessorFactory factory) {
399+
this.propertyAccessorFactory = factory;
400+
}
401+
402+
public PersistentPropertyAccessorFactory getPropertyAccessorFactory() {
403+
return propertyAccessorFactory;
404+
}
405+
406+
/*
407+
* (non-Javadoc)
408+
* @see org.springframework.data.mapping.PersistentEntity#getPropertyAccessor(java.lang.Object)
409+
*/
410+
@Override
399411
public PersistentPropertyAccessor getPropertyAccessor(Object bean) {
400412

401413
Assert.notNull(bean, "Target bean must not be null!");
402414
Assert.isTrue(getType().isInstance(bean), "Target bean is not of type of the persistent entity!");
403415

416+
if (propertyAccessorFactory == null) {
417+
return new BeanWrapper<Object>(bean);
418+
}
419+
404420
return propertyAccessorFactory.getPropertyAccessor(this, bean);
405421
}
406422

src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.springframework.data.mapping.SimpleAssociationHandler;
4848
import org.springframework.data.mapping.SimplePropertyHandler;
4949
import org.springframework.data.util.TypeInformation;
50+
import org.springframework.util.Assert;
5051
import org.springframework.util.ReflectionUtils;
5152

5253
/**
@@ -85,6 +86,16 @@ public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> ent
8586
}
8687
}
8788

89+
/* (non-Javadoc)
90+
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#isSupported(org.springframework.data.mapping.PersistentEntity)
91+
*/
92+
@Override
93+
public boolean isSupported(PersistentEntity<?, ?> entity) {
94+
95+
Assert.notNull(entity, "PersistentEntity must not be null!");
96+
return canGenerateAccessorClass(entity);
97+
}
98+
8899
/**
89100
* Checks whether an accessor class can be generated.
90101
*

src/main/java/org/springframework/data/mapping/model/DefaultPersistentPropertyAccessorFactory.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
/**
2222
* Default implementation of {@link PersistentPropertyAccessorFactory}. Accessors can access bean properties either via
2323
* reflection or use generated classes with direct field/method access.
24-
*
24+
*
2525
* @author Mark Paluch
2626
* @author Oliver Gierke
2727
* @since 1.13
@@ -37,7 +37,13 @@ public class DefaultPersistentPropertyAccessorFactory implements PersistentPrope
3737
@Override
3838
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
3939

40-
return ClassGeneratingPropertyAccessorFactory.canGenerateAccessorClass(entity)
41-
? classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean) : new BeanWrapper<Object>(bean);
40+
return classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean);
41+
}
42+
43+
/* (non-Javadoc)
44+
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#isSupported(org.springframework.data.mapping.PersistentEntity)
45+
*/
46+
public boolean isSupported(PersistentEntity<?, ?> entity) {
47+
return classGeneratingPropertyAccessorFactory.isSupported(entity);
4248
}
4349
}

0 commit comments

Comments
 (0)