36
36
import org .springframework .util .StringUtils ;
37
37
38
38
/**
39
- * Simple PropertyAccessor that uses reflection to access properties for reading and writing. A property can be accessed
40
- * if it is accessible as a field on the object or through a getter (if being read) or a setter (if being written).
39
+ * Simple PropertyAccessor that uses reflection to access properties for reading and writing.
40
+ * A property can be accessed if it is accessible as a field on the object or through a
41
+ * getter (if being read) or a setter (if being written).
41
42
*
42
43
* @author Andy Clement
43
44
* @author Juergen Hoeller
44
45
* @since 3.0
45
46
*/
46
47
public class ReflectivePropertyAccessor implements PropertyAccessor {
47
48
48
- protected final Map <CacheKey , InvokerPair > readerCache = new ConcurrentHashMap <CacheKey , InvokerPair >();
49
+ private final Map <CacheKey , InvokerPair > readerCache = new ConcurrentHashMap <CacheKey , InvokerPair >();
49
50
50
- protected final Map <CacheKey , Member > writerCache = new ConcurrentHashMap <CacheKey , Member >();
51
+ private final Map <CacheKey , Member > writerCache = new ConcurrentHashMap <CacheKey , Member >();
51
52
52
- protected final Map <CacheKey , TypeDescriptor > typeDescriptorCache = new ConcurrentHashMap <CacheKey , TypeDescriptor >();
53
+ private final Map <CacheKey , TypeDescriptor > typeDescriptorCache = new ConcurrentHashMap <CacheKey , TypeDescriptor >();
53
54
54
55
55
56
/**
@@ -365,52 +366,6 @@ protected Field findField(String name, Class<?> clazz, boolean mustBeStatic) {
365
366
return null ;
366
367
}
367
368
368
- /**
369
- * Captures the member (method/field) to call reflectively to access a property value and the type descriptor for the
370
- * value returned by the reflective call.
371
- */
372
- private static class InvokerPair {
373
-
374
- final Member member ;
375
-
376
- final TypeDescriptor typeDescriptor ;
377
-
378
- public InvokerPair (Member member , TypeDescriptor typeDescriptor ) {
379
- this .member = member ;
380
- this .typeDescriptor = typeDescriptor ;
381
- }
382
-
383
- }
384
-
385
- private static class CacheKey {
386
-
387
- private final Class clazz ;
388
-
389
- private final String name ;
390
-
391
- public CacheKey (Class clazz , String name ) {
392
- this .clazz = clazz ;
393
- this .name = name ;
394
- }
395
-
396
- @ Override
397
- public boolean equals (Object other ) {
398
- if (this == other ) {
399
- return true ;
400
- }
401
- if (!(other instanceof CacheKey )) {
402
- return false ;
403
- }
404
- CacheKey otherKey = (CacheKey ) other ;
405
- return (this .clazz .equals (otherKey .clazz ) && this .name .equals (otherKey .name ));
406
- }
407
-
408
- @ Override
409
- public int hashCode () {
410
- return this .clazz .hashCode () * 29 + this .name .hashCode ();
411
- }
412
- }
413
-
414
369
/**
415
370
* Attempt to create an optimized property accessor tailored for a property of a particular name on
416
371
* a particular class. The general ReflectivePropertyAccessor will always work but is not optimal
@@ -463,29 +418,82 @@ public PropertyAccessor createOptimalAccessor(EvaluationContext eContext, Object
463
418
return this ;
464
419
}
465
420
421
+
422
+ /**
423
+ * Captures the member (method/field) to call reflectively to access a property value
424
+ * and the type descriptor for the value returned by the reflective call.
425
+ */
426
+ private static class InvokerPair {
427
+
428
+ final Member member ;
429
+
430
+ final TypeDescriptor typeDescriptor ;
431
+
432
+ public InvokerPair (Member member , TypeDescriptor typeDescriptor ) {
433
+ this .member = member ;
434
+ this .typeDescriptor = typeDescriptor ;
435
+ }
436
+ }
437
+
438
+
439
+ private static class CacheKey {
440
+
441
+ private final Class clazz ;
442
+
443
+ private final String name ;
444
+
445
+ public CacheKey (Class clazz , String name ) {
446
+ this .clazz = clazz ;
447
+ this .name = name ;
448
+ }
449
+
450
+ @ Override
451
+ public boolean equals (Object other ) {
452
+ if (this == other ) {
453
+ return true ;
454
+ }
455
+ if (!(other instanceof CacheKey )) {
456
+ return false ;
457
+ }
458
+ CacheKey otherKey = (CacheKey ) other ;
459
+ return (this .clazz .equals (otherKey .clazz ) && this .name .equals (otherKey .name ));
460
+ }
461
+
462
+ @ Override
463
+ public int hashCode () {
464
+ return this .clazz .hashCode () * 29 + this .name .hashCode ();
465
+ }
466
+ }
467
+
468
+
466
469
/**
467
- * An optimized form of a PropertyAccessor that will use reflection but only knows how to access a particular property
468
- * on a particular class. This is unlike the general ReflectivePropertyResolver which manages a cache of methods/fields that
469
- * may be invoked to access different properties on different classes. This optimal accessor exists because looking up
470
- * the appropriate reflective object by class/name on each read is not cheap.
470
+ * An optimized form of a PropertyAccessor that will use reflection but only knows
471
+ * how to access a particular property on a particular class. This is unlike the
472
+ * general ReflectivePropertyResolver which manages a cache of methods/fields that
473
+ * may be invoked to access different properties on different classes. This optimal
474
+ * accessor exists because looking up the appropriate reflective object by class/name
475
+ * on each read is not cheap.
471
476
*/
472
- static class OptimalPropertyAccessor implements PropertyAccessor {
477
+ private static class OptimalPropertyAccessor implements PropertyAccessor {
478
+
473
479
private final Member member ;
480
+
474
481
private final TypeDescriptor typeDescriptor ;
482
+
475
483
private final boolean needsToBeMadeAccessible ;
476
484
477
485
OptimalPropertyAccessor (InvokerPair target ) {
478
486
this .member = target .member ;
479
487
this .typeDescriptor = target .typeDescriptor ;
480
488
if (this .member instanceof Field ) {
481
- Field field = (Field )member ;
482
- needsToBeMadeAccessible = (!Modifier .isPublic (field .getModifiers ()) || ! Modifier . isPublic ( field . getDeclaringClass (). getModifiers ()))
483
- && !field .isAccessible ();
489
+ Field field = (Field ) this . member ;
490
+ this . needsToBeMadeAccessible = (!Modifier .isPublic (field .getModifiers ()) ||
491
+ ! Modifier . isPublic ( field . getDeclaringClass (). getModifiers ())) && !field .isAccessible ();
484
492
}
485
493
else {
486
- Method method = (Method )member ;
487
- needsToBeMadeAccessible = ((!Modifier .isPublic (method .getModifiers ()) || ! Modifier . isPublic ( method . getDeclaringClass (). getModifiers ()))
488
- && !method .isAccessible ());
494
+ Method method = (Method ) this . member ;
495
+ this . needsToBeMadeAccessible = ((!Modifier .isPublic (method .getModifiers ()) ||
496
+ ! Modifier . isPublic ( method . getDeclaringClass (). getModifiers ())) && !method .isAccessible ());
489
497
}
490
498
}
491
499
@@ -501,8 +509,8 @@ public boolean canRead(EvaluationContext context, Object target, String name) th
501
509
if (type .isArray ()) {
502
510
return false ;
503
511
}
504
- if (member instanceof Method ) {
505
- Method method = (Method )member ;
512
+ if (this . member instanceof Method ) {
513
+ Method method = (Method ) this . member ;
506
514
String getterName = "get" + StringUtils .capitalize (name );
507
515
if (getterName .equals (method .getName ())) {
508
516
return true ;
@@ -511,31 +519,31 @@ public boolean canRead(EvaluationContext context, Object target, String name) th
511
519
return getterName .equals (method .getName ());
512
520
}
513
521
else {
514
- Field field = (Field )member ;
522
+ Field field = (Field ) this . member ;
515
523
return field .getName ().equals (name );
516
524
}
517
525
}
518
526
519
527
public TypedValue read (EvaluationContext context , Object target , String name ) throws AccessException {
520
- if (member instanceof Method ) {
528
+ if (this . member instanceof Method ) {
521
529
try {
522
- if (needsToBeMadeAccessible ) {
523
- ReflectionUtils .makeAccessible ((Method ) member );
530
+ if (this . needsToBeMadeAccessible ) {
531
+ ReflectionUtils .makeAccessible ((Method ) this . member );
524
532
}
525
- Object value = ((Method ) member ).invoke (target );
526
- return new TypedValue (value , typeDescriptor .narrow (value ));
533
+ Object value = ((Method ) this . member ).invoke (target );
534
+ return new TypedValue (value , this . typeDescriptor .narrow (value ));
527
535
}
528
536
catch (Exception ex ) {
529
537
throw new AccessException ("Unable to access property '" + name + "' through getter" , ex );
530
538
}
531
539
}
532
- if (member instanceof Field ) {
540
+ if (this . member instanceof Field ) {
533
541
try {
534
- if (needsToBeMadeAccessible ) {
535
- ReflectionUtils .makeAccessible ((Field )member );
542
+ if (this . needsToBeMadeAccessible ) {
543
+ ReflectionUtils .makeAccessible ((Field ) this . member );
536
544
}
537
- Object value = ((Field )member ).get (target );
538
- return new TypedValue (value , typeDescriptor .narrow (value ));
545
+ Object value = ((Field ) this . member ).get (target );
546
+ return new TypedValue (value , this . typeDescriptor .narrow (value ));
539
547
}
540
548
catch (Exception ex ) {
541
549
throw new AccessException ("Unable to access field: " + name , ex );
@@ -544,12 +552,11 @@ public TypedValue read(EvaluationContext context, Object target, String name) th
544
552
throw new AccessException ("Neither getter nor field found for property '" + name + "'" );
545
553
}
546
554
547
- public boolean canWrite (EvaluationContext context , Object target , String name ) throws AccessException {
555
+ public boolean canWrite (EvaluationContext context , Object target , String name ) {
548
556
throw new UnsupportedOperationException ("Should not be called on an OptimalPropertyAccessor" );
549
557
}
550
558
551
- public void write (EvaluationContext context , Object target , String name , Object newValue )
552
- throws AccessException {
559
+ public void write (EvaluationContext context , Object target , String name , Object newValue ) {
553
560
throw new UnsupportedOperationException ("Should not be called on an OptimalPropertyAccessor" );
554
561
}
555
562
}
0 commit comments