20
20
21
21
import lombok .AccessLevel ;
22
22
import lombok .AllArgsConstructor ;
23
+ import lombok .NonNull ;
23
24
import lombok .RequiredArgsConstructor ;
24
25
25
- import java .beans .PropertyDescriptor ;
26
26
import java .io .IOException ;
27
27
import java .util .ArrayList ;
28
28
import java .util .Collection ;
@@ -180,7 +180,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
180
180
private static final String ID_FIELD = "_id" ;
181
181
private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking .NONE ;
182
182
private static final Collection <String > ITERABLE_CLASSES ;
183
- public static final SpelAwareProxyProjectionFactory PROJECTION_FACTORY = new SpelAwareProxyProjectionFactory ();
184
183
185
184
static {
186
185
@@ -198,6 +197,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
198
197
private final PersistenceExceptionTranslator exceptionTranslator ;
199
198
private final QueryMapper queryMapper ;
200
199
private final UpdateMapper updateMapper ;
200
+ private final SpelAwareProxyProjectionFactory projectionFactory ;
201
201
202
202
private WriteConcern writeConcern ;
203
203
private WriteConcernResolver writeConcernResolver = DefaultWriteConcernResolver .INSTANCE ;
@@ -241,6 +241,7 @@ public MongoTemplate(MongoDbFactory mongoDbFactory, MongoConverter mongoConverte
241
241
this .mongoConverter = mongoConverter == null ? getDefaultMongoConverter (mongoDbFactory ) : mongoConverter ;
242
242
this .queryMapper = new QueryMapper (this .mongoConverter );
243
243
this .updateMapper = new UpdateMapper (this .mongoConverter );
244
+ this .projectionFactory = new SpelAwareProxyProjectionFactory ();
244
245
245
246
// We always have a mapping context in the converter, whether it's a simple one or not
246
247
mappingContext = this .mongoConverter .getMappingContext ();
@@ -303,10 +304,15 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
303
304
prepareIndexCreator (applicationContext );
304
305
305
306
eventPublisher = applicationContext ;
307
+
306
308
if (mappingContext instanceof ApplicationEventPublisherAware ) {
307
309
((ApplicationEventPublisherAware ) mappingContext ).setApplicationEventPublisher (eventPublisher );
308
310
}
311
+
309
312
resourceLoader = applicationContext ;
313
+
314
+ projectionFactory .setBeanFactory (applicationContext );
315
+ projectionFactory .setBeanClassLoader (applicationContext .getClassLoader ());
310
316
}
311
317
312
318
/**
@@ -2356,12 +2362,10 @@ private Document addFieldsForProjection(Document fields, Class<?> domainType, Cl
2356
2362
return fields ;
2357
2363
}
2358
2364
2359
- ProjectionInformation projectionInformation = PROJECTION_FACTORY .getProjectionInformation (targetType );
2360
- if (projectionInformation .isClosed ()) {
2365
+ ProjectionInformation projectionInformation = projectionFactory .getProjectionInformation (targetType );
2361
2366
2362
- for (PropertyDescriptor descriptor : projectionInformation .getInputProperties ()) {
2363
- fields .append (descriptor .getName (), 1 );
2364
- }
2367
+ if (projectionInformation .isClosed ()) {
2368
+ projectionInformation .getInputProperties ().forEach (it -> fields .append (it .getName (), 1 ));
2365
2369
}
2366
2370
2367
2371
return fields ;
@@ -2612,46 +2616,35 @@ public T doWith(Document object) {
2612
2616
* @param <T>
2613
2617
* @since 2.0
2614
2618
*/
2615
- class ProjectingReadCallback <S , T > implements DocumentCallback <T > {
2616
-
2617
- private final Class <S > entityType ;
2618
- private final Class <T > targetType ;
2619
- private final String collectionName ;
2620
- private final EntityReader <Object , Bson > reader ;
2621
-
2622
- ProjectingReadCallback (EntityReader <Object , Bson > reader , Class <S > entityType , Class <T > targetType ,
2623
- String collectionName ) {
2619
+ @ RequiredArgsConstructor
2620
+ private class ProjectingReadCallback <S , T > implements DocumentCallback <T > {
2624
2621
2625
- this .reader = reader ;
2626
- this .entityType = entityType ;
2627
- this .targetType = targetType ;
2628
- this .collectionName = collectionName ;
2629
- }
2622
+ private final @ NonNull EntityReader <Object , Bson > reader ;
2623
+ private final @ NonNull Class <S > entityType ;
2624
+ private final @ NonNull Class <T > targetType ;
2625
+ private final @ NonNull String collectionName ;
2630
2626
2627
+ /*
2628
+ * (non-Javadoc)
2629
+ * @see org.springframework.data.mongodb.core.MongoTemplate.DocumentCallback#doWith(org.bson.Document)
2630
+ */
2631
+ @ SuppressWarnings ("unchecked" )
2631
2632
public T doWith (Document object ) {
2632
2633
2633
- if (null != object ) {
2634
- maybeEmitEvent (new AfterLoadEvent <>(object , targetType , collectionName ));
2635
- }
2636
-
2637
- T target = doRead (object , entityType , targetType );
2638
-
2639
- if (null != target ) {
2640
- maybeEmitEvent (new AfterConvertEvent <>(object , target , collectionName ));
2634
+ if (object == null ) {
2635
+ return null ;
2641
2636
}
2642
2637
2643
- return target ;
2644
- }
2645
-
2646
- private T doRead (Document source , Class entityType , Class targetType ) {
2647
-
2648
- if (targetType != entityType && targetType .isInterface ()) {
2638
+ Class <?> typeToRead = targetType .isInterface () || targetType .isAssignableFrom (entityType ) ? entityType
2639
+ : targetType ;
2640
+ Object source = reader .read (typeToRead , object );
2641
+ Object result = targetType .isInterface () ? projectionFactory .createProjection (targetType , source ) : source ;
2649
2642
2650
- S target = ( S ) reader . read ( entityType , source );
2651
- return ( T ) PROJECTION_FACTORY . createProjection ( targetType , target );
2643
+ if ( result == null ) {
2644
+ maybeEmitEvent ( new AfterConvertEvent <>( object , result , collectionName ) );
2652
2645
}
2653
2646
2654
- return (T ) reader . read ( targetType , source ) ;
2647
+ return (T ) result ;
2655
2648
}
2656
2649
}
2657
2650
0 commit comments