3232import org .springframework .beans .factory .BeanClassLoaderAware ;
3333import org .springframework .context .ApplicationContext ;
3434import org .springframework .context .ApplicationContextAware ;
35+ import org .springframework .context .EnvironmentAware ;
3536import org .springframework .core .CollectionFactory ;
3637import org .springframework .core .convert .ConversionService ;
3738import org .springframework .core .convert .support .DefaultConversionService ;
39+ import org .springframework .core .env .Environment ;
40+ import org .springframework .core .env .EnvironmentCapable ;
41+ import org .springframework .core .env .StandardEnvironment ;
3842import org .springframework .dao .InvalidDataAccessApiUsageException ;
3943import org .springframework .data .cassandra .core .mapping .*;
4044import org .springframework .data .cassandra .core .mapping .Embedded .OnEmpty ;
4650import org .springframework .data .mapping .PersistentProperty ;
4751import org .springframework .data .mapping .PersistentPropertyAccessor ;
4852import org .springframework .data .mapping .context .MappingContext ;
53+ import org .springframework .data .mapping .model .CachingValueExpressionEvaluatorFactory ;
4954import org .springframework .data .mapping .model .ConvertingPropertyAccessor ;
50- import org .springframework .data .mapping .model .DefaultSpELExpressionEvaluator ;
5155import org .springframework .data .mapping .model .EntityInstantiator ;
5256import org .springframework .data .mapping .model .ParameterValueProvider ;
5357import org .springframework .data .mapping .model .PropertyValueProvider ;
5458import org .springframework .data .mapping .model .SpELContext ;
55- import org .springframework .data .mapping .model .SpELExpressionEvaluator ;
56- import org .springframework .data .mapping .model .SpELExpressionParameterValueProvider ;
59+ import org .springframework .data .mapping .model .ValueExpressionEvaluator ;
60+ import org .springframework .data .mapping .model .ValueExpressionParameterValueProvider ;
5761import org .springframework .data .projection .EntityProjection ;
5862import org .springframework .data .projection .ProjectionFactory ;
5963import org .springframework .data .projection .SpelAwareProxyProjectionFactory ;
6064import org .springframework .data .util .Predicates ;
6165import org .springframework .data .util .TypeInformation ;
66+ import org .springframework .expression .spel .standard .SpelExpressionParser ;
6267import org .springframework .lang .Nullable ;
6368import org .springframework .util .Assert ;
6469import org .springframework .util .ClassUtils ;
8792 * @author Frank Spitulski
8893 */
8994public class MappingCassandraConverter extends AbstractCassandraConverter
90- implements ApplicationContextAware , BeanClassLoaderAware {
95+ implements ApplicationContextAware , EnvironmentAware , EnvironmentCapable , BeanClassLoaderAware {
9196
9297 private final Log log = LogFactory .getLog (getClass ());
9398
@@ -99,11 +104,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter
99104
100105 private @ Nullable ClassLoader beanClassLoader ;
101106
107+ private @ Nullable Environment environment ;
108+
102109 private SpELContext spELContext ;
103110
104111 private final DefaultColumnTypeResolver cassandraTypeResolver ;
112+
105113 private final EmbeddedEntityOperations embeddedEntityOperations ;
106- private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory ();
114+
115+ private final SpelExpressionParser expressionParser = new SpelExpressionParser ();
116+
117+ private final SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory (
118+ expressionParser );
119+
120+ private final CachingValueExpressionEvaluatorFactory expressionEvaluatorFactory = new CachingValueExpressionEvaluatorFactory (
121+ expressionParser , this , o -> spELContext .getEvaluationContext (o ));
107122
108123 /**
109124 * Create a new {@link MappingCassandraConverter} with a {@link CassandraMappingContext}.
@@ -171,10 +186,30 @@ private static CassandraMappingContext newDefaultMappingContext(CassandraCustomC
171186
172187 @ Override
173188 public void setApplicationContext (ApplicationContext applicationContext ) throws BeansException {
189+
174190 this .spELContext = new SpELContext (this .spELContext , applicationContext );
191+ this .environment = applicationContext .getEnvironment ();
175192 this .projectionFactory .setBeanFactory (applicationContext );
176193 }
177194
195+ @ Override
196+ public void setEnvironment (Environment environment ) {
197+ this .environment = environment ;
198+ }
199+
200+ @ Override
201+ public Environment getEnvironment () {
202+
203+ if (this .environment == null ) {
204+ this .environment = new StandardEnvironment ();
205+ }
206+ return this .environment ;
207+ }
208+
209+ public void setSpELContext (SpELContext spELContext ) {
210+ this .spELContext = spELContext ;
211+ }
212+
178213 @ Override
179214 public void setBeanClassLoader (ClassLoader classLoader ) {
180215 this .beanClassLoader = classLoader ;
@@ -294,8 +329,7 @@ public <R> R project(EntityProjection<R, ?> projection, Row row) {
294329 this ::doReadTupleValue , this ::doReadUdtValue , this ::readCollectionOrArray , this ::readMap ,
295330 this ::getPotentiallyConvertedSimpleRead , projection );
296331
297- return doReadProjection (context , new RowValueProvider (row , new DefaultSpELExpressionEvaluator (row , spELContext )),
298- projection );
332+ return doReadProjection (context , new RowValueProvider (row , expressionEvaluatorFactory .create (row )), projection );
299333 }
300334
301335 @ SuppressWarnings ("unchecked" )
@@ -334,11 +368,10 @@ private <R> R doReadProjection(ConversionContext context, CassandraValueProvider
334368
335369 ParameterValueProvider <CassandraPersistentProperty > provider ;
336370 if (persistenceCreator != null && persistenceCreator .hasParameters ()) {
337- SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (valueProviderToUse .getSource (),
338- spELContext );
371+ ValueExpressionEvaluator evaluator = expressionEvaluatorFactory .create (valueProviderToUse .getSource ());
339372 ParameterValueProvider <CassandraPersistentProperty > parameterValueProvider = newParameterValueProvider (context ,
340373 entity , valueProviderToUse );
341- provider = new ConverterAwareSpELExpressionParameterValueProvider (evaluator , getConversionService (),
374+ provider = new ConverterAwareValueExpressionParameterValueProvider (evaluator , getConversionService (),
342375 parameterValueProvider , context );
343376 } else {
344377 provider = NoOpParameterValueProvider .INSTANCE ;
@@ -362,8 +395,7 @@ private Object doReadOrProject(ConversionContext context, Row row, TypeInformati
362395
363396 if (typeDescriptor .isProjection ()) {
364397
365- CassandraValueProvider valueProvider = new RowValueProvider (row ,
366- new DefaultSpELExpressionEvaluator (row , this .spELContext ));
398+ CassandraValueProvider valueProvider = new RowValueProvider (row , expressionEvaluatorFactory .create (row ));
367399 return doReadProjection (context , valueProvider , typeDescriptor );
368400 }
369401
@@ -376,7 +408,7 @@ private Object doReadOrProject(ConversionContext context, UdtValue udtValue, Typ
376408 if (typeDescriptor .isProjection ()) {
377409
378410 CassandraValueProvider valueProvider = new UdtValueProvider (udtValue ,
379- new DefaultSpELExpressionEvaluator (udtValue , this . spELContext ));
411+ expressionEvaluatorFactory . create (udtValue ));
380412 return doReadProjection (context , valueProvider , typeDescriptor );
381413 }
382414
@@ -389,7 +421,7 @@ private Object doReadOrProject(ConversionContext context, TupleValue tupleValue,
389421 if (typeDescriptor .isProjection ()) {
390422
391423 CassandraValueProvider valueProvider = new TupleValueProvider (tupleValue ,
392- new DefaultSpELExpressionEvaluator (tupleValue , this . spELContext ));
424+ expressionEvaluatorFactory . create (tupleValue ));
393425 return doReadProjection (context , valueProvider , typeDescriptor );
394426 }
395427
@@ -436,10 +468,10 @@ <S> S doReadUdtValue(ConversionContext context, UdtValue udtValue, TypeInformati
436468 }
437469
438470 private <S > S doReadEntity (ConversionContext context , Object value ,
439- Function <SpELExpressionEvaluator , CassandraValueProvider > valueProviderSupplier ,
471+ Function <ValueExpressionEvaluator , CassandraValueProvider > valueProviderSupplier ,
440472 TypeInformation <? extends S > typeHint ) {
441473
442- SpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator (value , this . spELContext );
474+ ValueExpressionEvaluator expressionEvaluator = expressionEvaluatorFactory . create (value );
443475 CassandraValueProvider valueProvider = valueProviderSupplier .apply (expressionEvaluator );
444476
445477 return doReadEntity (context , valueProvider , typeHint );
@@ -507,10 +539,10 @@ private <S> S doReadEntity(ConversionContext context, CassandraValueProvider val
507539 ParameterValueProvider <CassandraPersistentProperty > provider ;
508540
509541 if (persistenceCreator != null && persistenceCreator .hasParameters ()) {
510- SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator (valueProvider .getSource (), spELContext );
542+ ValueExpressionEvaluator evaluator = expressionEvaluatorFactory . create (valueProvider .getSource ());
511543 ParameterValueProvider <CassandraPersistentProperty > parameterValueProvider = newParameterValueProvider (context ,
512544 entity , valueProvider );
513- provider = new ConverterAwareSpELExpressionParameterValueProvider (evaluator , getConversionService (),
545+ provider = new ConverterAwareValueExpressionParameterValueProvider (evaluator , getConversionService (),
514546 parameterValueProvider , context );
515547 } else {
516548 provider = NoOpParameterValueProvider .INSTANCE ;
@@ -1261,23 +1293,23 @@ public <T> T getParameterValue(Parameter<T, CassandraPersistentProperty> paramet
12611293 }
12621294
12631295 /**
1264- * Extension of {@link SpELExpressionParameterValueProvider } to recursively trigger value conversion on the raw
1296+ * Extension of {@link ValueExpressionParameterValueProvider } to recursively trigger value conversion on the raw
12651297 * resolved SpEL value.
12661298 */
1267- private static class ConverterAwareSpELExpressionParameterValueProvider
1268- extends SpELExpressionParameterValueProvider <CassandraPersistentProperty > {
1299+ private static class ConverterAwareValueExpressionParameterValueProvider
1300+ extends ValueExpressionParameterValueProvider <CassandraPersistentProperty > {
12691301
12701302 private final ConversionContext context ;
12711303
12721304 /**
1273- * Creates a new {@link ConverterAwareSpELExpressionParameterValueProvider }.
1305+ * Creates a new {@link ConverterAwareValueExpressionParameterValueProvider }.
12741306 *
12751307 * @param evaluator must not be {@literal null}.
12761308 * @param conversionService must not be {@literal null}.
12771309 * @param delegate must not be {@literal null}.
12781310 * @param context must not be {@literal null}.
12791311 */
1280- public ConverterAwareSpELExpressionParameterValueProvider ( SpELExpressionEvaluator evaluator ,
1312+ public ConverterAwareValueExpressionParameterValueProvider ( ValueExpressionEvaluator evaluator ,
12811313 ConversionService conversionService , ParameterValueProvider <CassandraPersistentProperty > delegate ,
12821314 ConversionContext context ) {
12831315
@@ -1286,8 +1318,9 @@ public ConverterAwareSpELExpressionParameterValueProvider(SpELExpressionEvaluato
12861318 }
12871319
12881320 @ Override
1289- protected <T > T potentiallyConvertSpelValue (Object object , Parameter <T , CassandraPersistentProperty > parameter ) {
1290- return (T ) context .convert (object , parameter .getType ());
1321+ protected <T > T potentiallyConvertExpressionValue (Object object ,
1322+ Parameter <T , CassandraPersistentProperty > parameter ) {
1323+ return context .convert (object , parameter .getType ());
12911324 }
12921325 }
12931326
0 commit comments