0
# Property Access and Type Conversion
1
2
Powerful property binding system with automatic type conversion, nested property access, and comprehensive editor support for converting between string representations and Java objects. This system forms the foundation for Spring's data binding capabilities in web applications and configuration processing.
3
4
## Capabilities
5
6
### Property Accessor Interface
7
8
Core interface for accessing and modifying properties on target objects with support for nested properties and automatic type conversion.
9
10
```java { .api }
11
/**
12
* Common interface for classes that can access named properties (such as bean properties of an object or fields in an object).
13
*/
14
interface PropertyAccessor {
15
/** Path separator for nested properties. */
16
String NESTED_PROPERTY_SEPARATOR = ".";
17
/** Path separator for nested properties. */
18
char NESTED_PROPERTY_SEPARATOR_CHAR = '.';
19
/** Marker that indicates the start of a property key for an indexed or mapped property. */
20
String PROPERTY_KEY_PREFIX = "[";
21
/** Marker that indicates the start of a property key for an indexed or mapped property. */
22
char PROPERTY_KEY_PREFIX_CHAR = '[';
23
/** Marker that indicates the end of a property key for an indexed or mapped property. */
24
String PROPERTY_KEY_SUFFIX = "]";
25
/** Marker that indicates the end of a property key for an indexed or mapped property. */
26
char PROPERTY_KEY_SUFFIX_CHAR = ']';
27
28
/**
29
* Determine whether the specified property is readable.
30
* @param propertyName the property to check
31
* @return whether the property is readable
32
*/
33
boolean isReadableProperty(String propertyName);
34
35
/**
36
* Determine whether the specified property is writable.
37
* @param propertyName the property to check
38
* @return whether the property is writable
39
*/
40
boolean isWritableProperty(String propertyName);
41
42
/**
43
* Determine the property type for the specified property.
44
* @param propertyName the property to check
45
* @return the type of the property, or null if not determinable
46
* @throws InvalidPropertyException if there is no such property or if the property isn't readable
47
*/
48
Class<?> getPropertyType(String propertyName) throws BeansException;
49
50
/**
51
* Return a type descriptor for the specified property.
52
* @param propertyName the property to check
53
* @return the type descriptor for the particular property
54
* @throws InvalidPropertyException if there is no such property or if the property isn't readable
55
*/
56
TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
57
58
/**
59
* Get the current value of the specified property.
60
* @param propertyName the name of the property to get the value of
61
* @return the value of the property
62
* @throws InvalidPropertyException if there is no such property or if the property isn't readable
63
* @throws PropertyAccessException if the property was valid but the accessor method failed
64
*/
65
Object getPropertyValue(String propertyName) throws BeansException;
66
67
/**
68
* Set the specified value as current property value.
69
* @param propertyName the name of the property to set the value of
70
* @param value the new value
71
* @throws InvalidPropertyException if there is no such property or if the property isn't writable
72
* @throws PropertyAccessException if the property was valid but the accessor method failed or a type mismatch occurred
73
*/
74
void setPropertyValue(String propertyName, Object value) throws BeansException;
75
76
/**
77
* Set the specified value as current property value.
78
* @param pv an object containing the new property value
79
* @throws InvalidPropertyException if there is no such property or if the property isn't writable
80
* @throws PropertyAccessException if the property was valid but the accessor method failed or a type mismatch occurred
81
*/
82
void setPropertyValue(PropertyValue pv) throws BeansException;
83
84
/**
85
* Perform a batch update from a Map.
86
* @param map Map containing properties to set, as name-value pairs
87
* @throws InvalidPropertyException if there is no such property or if the property isn't writable
88
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions occurred for specific properties during the batch update
89
*/
90
void setPropertyValues(Map<?, ?> map) throws BeansException;
91
92
/**
93
* The preferred way to perform a batch update.
94
* @param pvs PropertyValues to set on the target object
95
* @throws InvalidPropertyException if there is no such property or if the property isn't writable
96
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions occurred for specific properties during the batch update
97
*/
98
void setPropertyValues(PropertyValues pvs) throws BeansException;
99
100
/**
101
* Perform a batch update with more control over behavior.
102
* @param pvs PropertyValues to set on the target object
103
* @param ignoreUnknown should we ignore unknown properties (not found in the bean)
104
* @throws InvalidPropertyException if there is no such property or if the property isn't writable
105
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions occurred for specific properties during the batch update
106
*/
107
void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown) throws BeansException;
108
109
/**
110
* Perform a batch update with full control over behavior.
111
* @param pvs PropertyValues to set on the target object
112
* @param ignoreUnknown should we ignore unknown properties (not found in the bean)
113
* @param ignoreInvalid should we ignore invalid properties (found but not accessible)
114
* @throws InvalidPropertyException if there is no such property or if the property isn't writable
115
* @throws PropertyBatchUpdateException if one or more PropertyAccessExceptions occurred for specific properties during the batch update
116
*/
117
void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException;
118
}
119
```
120
121
### Bean Wrapper Interface
122
123
Central interface for accessing and manipulating the properties of a bean instance, combining property access with comprehensive type conversion.
124
125
```java { .api }
126
/**
127
* The central interface of Spring's low-level JavaBeans infrastructure.
128
*/
129
interface BeanWrapper extends ConfigurablePropertyAccessor {
130
/**
131
* Change the wrapped object. Implementations are required to allow the type of the wrapped object to change.
132
* @param object the new wrapped object
133
*/
134
void setWrappedInstance(Object object);
135
136
/**
137
* Return the bean instance wrapped by this object.
138
* @return the bean instance, or null if none set
139
*/
140
Object getWrappedInstance();
141
142
/**
143
* Return the type of the wrapped bean instance.
144
* @return the type of the wrapped bean instance, or null if no wrapped object has been set
145
*/
146
Class<?> getWrappedClass();
147
148
/**
149
* Obtain the PropertyDescriptors for the wrapped object (as determined by standard JavaBeans introspection).
150
* @return the PropertyDescriptors for the wrapped object
151
*/
152
PropertyDescriptor[] getPropertyDescriptors();
153
154
/**
155
* Obtain the property descriptor for a specific property of the wrapped object.
156
* @param propertyName the property to obtain the descriptor for
157
* @return the property descriptor for the specified property
158
* @throws InvalidPropertyException if there is no such property
159
*/
160
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
161
}
162
```
163
164
### Bean Wrapper Implementation
165
166
Default implementation of the BeanWrapper interface that provides comprehensive property access and type conversion capabilities.
167
168
```java { .api }
169
/**
170
* Default BeanWrapper implementation that should be sufficient for all typical use cases.
171
*/
172
class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper {
173
/**
174
* Create a new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
175
*/
176
public BeanWrapperImpl();
177
178
/**
179
* Create a new BeanWrapperImpl for the given object.
180
* @param object the object wrapped by this BeanWrapper
181
*/
182
public BeanWrapperImpl(Object object);
183
184
/**
185
* Create a new BeanWrapperImpl, wrapping a new instance of the specified class.
186
* @param clazz class to instantiate and wrap
187
*/
188
public BeanWrapperImpl(Class<?> clazz);
189
190
/**
191
* Create a new BeanWrapperImpl for the given object, registering a nested path that the object is in.
192
* @param object the object wrapped by this BeanWrapper
193
* @param nestedPath the nested path of the object
194
* @param rootObject the root object at the top of the path
195
*/
196
public BeanWrapperImpl(Object object, String nestedPath, Object rootObject);
197
198
/**
199
* Set a bean instance to hold, without any unwrapping of Optional.
200
* @param object the actual target object
201
*/
202
public void setBeanInstance(Object object);
203
204
/**
205
* Convert the given value for the specified property to the latter's type.
206
* @param value the value to convert (may be null)
207
* @param propertyName the target property
208
* @return the converted value
209
* @throws TypeMismatchException if type conversion failed
210
*/
211
public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException;
212
}
213
```
214
215
### Property Values Support
216
217
Container for PropertyValue objects, typically representing one update for a JavaBean.
218
219
```java { .api }
220
/**
221
* Holder containing one or more PropertyValue objects, typically comprising one update for a specific target bean.
222
*/
223
interface PropertyValues {
224
/**
225
* Return an array of the PropertyValue objects held in this object.
226
* @return an array of the PropertyValue objects held in this object (never null)
227
*/
228
PropertyValue[] getPropertyValues();
229
230
/**
231
* Return the property value with the given name, if any.
232
* @param propertyName the name to search for
233
* @return the property value, or null if none
234
*/
235
PropertyValue getPropertyValue(String propertyName);
236
237
/**
238
* Return the changes since the previous PropertyValues.
239
* @param old the old property values
240
* @return the updated or new properties
241
*/
242
PropertyValues changesSince(PropertyValues old);
243
244
/**
245
* Is there a property value (or other processing entry) for this property?
246
* @param propertyName the name of the property we're interested in
247
* @return whether there is a property value for this property
248
*/
249
boolean contains(String propertyName);
250
251
/**
252
* Does this holder not contain any PropertyValue objects at all?
253
* @return whether this holder does not contain any PropertyValue objects
254
*/
255
boolean isEmpty();
256
257
/**
258
* Return the number of PropertyValue objects held in this object.
259
* @return the number of PropertyValue objects held in this object
260
*/
261
int size();
262
}
263
264
/**
265
* The default implementation of the PropertyValues interface.
266
*/
267
class MutablePropertyValues implements PropertyValues {
268
/**
269
* Creates a new empty MutablePropertyValues object.
270
*/
271
public MutablePropertyValues();
272
273
/**
274
* Deep copy constructor.
275
* @param original the PropertyValues to copy
276
*/
277
public MutablePropertyValues(PropertyValues original);
278
279
/**
280
* Construct a new MutablePropertyValues object from a Map.
281
* @param original a Map with property values keyed by property name Strings
282
*/
283
public MutablePropertyValues(Map<?, ?> original);
284
285
/**
286
* Construct a new MutablePropertyValues object using the given List of PropertyValue objects as-is.
287
* @param propertyValueList a List of PropertyValue objects
288
*/
289
public MutablePropertyValues(List<PropertyValue> propertyValueList);
290
291
/**
292
* Return the underlying List of PropertyValue objects in its raw form.
293
* @return the underlying List of PropertyValue objects
294
*/
295
public List<PropertyValue> getPropertyValueList();
296
297
/**
298
* Add all property values from the given PropertyValues object.
299
* @param other the PropertyValues object to add property values from
300
* @return this in order to allow for adding multiple property values in a chain
301
*/
302
public MutablePropertyValues addPropertyValues(PropertyValues other);
303
304
/**
305
* Add all property values from the given Map.
306
* @param other a Map with property values keyed by property name Strings
307
* @return this in order to allow for adding multiple property values in a chain
308
*/
309
public MutablePropertyValues addPropertyValues(Map<?, ?> other);
310
311
/**
312
* Add a PropertyValue object, replacing any existing one for the corresponding property or getting merged with it (if applicable).
313
* @param pv the PropertyValue object to add
314
* @return this in order to allow for adding multiple property values in a chain
315
*/
316
public MutablePropertyValues addPropertyValue(PropertyValue pv);
317
318
/**
319
* Add a PropertyValue object, replacing any existing one for the corresponding property.
320
* @param propertyName name of the property
321
* @param propertyValue value of the property
322
* @return this in order to allow for adding multiple property values in a chain
323
*/
324
public MutablePropertyValues addPropertyValue(String propertyName, Object propertyValue);
325
326
/**
327
* Add a PropertyValue object, replacing any existing one for the corresponding property.
328
* @param propertyName name of the property
329
* @param propertyValue value of the property
330
* @return this in order to allow for adding multiple property values in a chain
331
*/
332
public MutablePropertyValues add(String propertyName, Object propertyValue);
333
334
/**
335
* Remove the given PropertyValue, if contained.
336
* @param pv the PropertyValue to remove
337
*/
338
public void removePropertyValue(PropertyValue pv);
339
340
/**
341
* Overloaded version of removePropertyValue that takes a property name.
342
* @param propertyName name of the property to remove
343
*/
344
public void removePropertyValue(String propertyName);
345
}
346
347
/**
348
* Object to hold information and value for an individual bean property.
349
*/
350
class PropertyValue extends BeanMetadataAttributeAccessor {
351
/**
352
* Create a new PropertyValue instance.
353
* @param name the name of the property (never null)
354
* @param value the value of the property (possibly before type conversion)
355
*/
356
public PropertyValue(String name, Object value);
357
358
/**
359
* Copy constructor.
360
* @param original the PropertyValue to copy (never null)
361
*/
362
public PropertyValue(PropertyValue original);
363
364
/**
365
* Constructor that exposes a new value for an original value holder.
366
* @param original the PropertyValue to link to (never null)
367
* @param newValue the new value to apply
368
*/
369
public PropertyValue(PropertyValue original, Object newValue);
370
371
/**
372
* Return the name of the property.
373
* @return the name of the property (never null)
374
*/
375
public String getName();
376
377
/**
378
* Return the value of the property.
379
* @return the value of the property (possibly before type conversion)
380
*/
381
public Object getValue();
382
383
/**
384
* Return the original PropertyValue instance for this value holder.
385
* @return the original PropertyValue (either a source of this value holder or this value holder itself)
386
*/
387
public PropertyValue getOriginalPropertyValue();
388
389
/**
390
* Set whether this is an optional value, that is, to be ignored when no corresponding property exists on the target class.
391
* @param optional whether this is an optional value
392
*/
393
public void setOptional(boolean optional);
394
395
/**
396
* Return whether this is an optional value, that is, to be ignored when no corresponding property exists on the target class.
397
* @return whether this is an optional value
398
*/
399
public boolean isOptional();
400
401
/**
402
* Return whether this holder contains a converted value already (true), or whether the value still needs to be converted (false).
403
* @return whether this holder contains a converted value already
404
*/
405
public synchronized boolean isConverted();
406
407
/**
408
* Set the converted value of the constructor argument, after processed type conversion.
409
* @param value the converted value
410
*/
411
public synchronized void setConvertedValue(Object value);
412
413
/**
414
* Return the converted value of the constructor argument, after processed type conversion.
415
* @return the converted value
416
*/
417
public synchronized Object getConvertedValue();
418
}
419
```
420
421
### Type Conversion Support
422
423
Core interfaces and classes for type conversion between different object types.
424
425
```java { .api }
426
/**
427
* Interface that defines type conversion methods.
428
*/
429
interface TypeConverter {
430
/**
431
* Convert the value to the required type (if necessary from a String).
432
* @param value the value to convert
433
* @param requiredType the type we must convert to (or null if not known)
434
* @return the new value, possibly the result of type conversion
435
* @throws TypeMismatchException if type conversion failed
436
*/
437
<T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException;
438
439
/**
440
* Convert the value to the required type (if necessary from a String).
441
* @param value the value to convert
442
* @param requiredType the type we must convert to (or null if not known)
443
* @param methodParam the method parameter that is the target of the conversion
444
* @return the new value, possibly the result of type conversion
445
* @throws TypeMismatchException if type conversion failed
446
*/
447
<T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException;
448
449
/**
450
* Convert the value to the required type (if necessary from a String).
451
* @param value the value to convert
452
* @param requiredType the type we must convert to (or null if not known)
453
* @param field the reflective field that is the target of the conversion
454
* @return the new value, possibly the result of type conversion
455
* @throws TypeMismatchException if type conversion failed
456
*/
457
<T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException;
458
459
/**
460
* Convert the value to the required type (if necessary from a String).
461
* @param value the value to convert
462
* @param requiredType the type we must convert to (or null if not known)
463
* @param typeDescriptor the type descriptor to use (may be null)
464
* @return the new value, possibly the result of type conversion
465
* @throws TypeMismatchException if type conversion failed
466
*/
467
<T> T convertIfNecessary(Object value, Class<T> requiredType, TypeDescriptor typeDescriptor) throws TypeMismatchException;
468
}
469
470
/**
471
* Simple implementation of the TypeConverter interface that does not operate on a specific target object.
472
*/
473
class SimpleTypeConverter extends TypeConverterSupport {
474
/**
475
* Create a new SimpleTypeConverter.
476
*/
477
public SimpleTypeConverter();
478
}
479
```
480
481
**Usage Examples:**
482
483
```java
484
import org.springframework.beans.BeanWrapper;
485
import org.springframework.beans.BeanWrapperImpl;
486
import org.springframework.beans.MutablePropertyValues;
487
import org.springframework.beans.PropertyValue;
488
489
// Basic property access
490
Person person = new Person();
491
BeanWrapper wrapper = new BeanWrapperImpl(person);
492
493
// Set simple properties
494
wrapper.setPropertyValue("name", "John Doe");
495
wrapper.setPropertyValue("age", 30);
496
wrapper.setPropertyValue("active", true);
497
498
// Get property values
499
String name = (String) wrapper.getPropertyValue("name");
500
Integer age = (Integer) wrapper.getPropertyValue("age");
501
502
// Nested property access
503
wrapper.setPropertyValue("address.street", "123 Main St");
504
wrapper.setPropertyValue("address.city", "New York");
505
506
// Batch property updates
507
MutablePropertyValues pvs = new MutablePropertyValues();
508
pvs.addPropertyValue("name", "Jane Smith");
509
pvs.addPropertyValue("email", "jane@example.com");
510
pvs.addPropertyValue("birthDate", "1990-01-15");
511
512
wrapper.setPropertyValues(pvs);
513
514
// Array and collection property access
515
wrapper.setPropertyValue("hobbies[0]", "Reading");
516
wrapper.setPropertyValue("hobbies[1]", "Swimming");
517
518
// Map property access
519
wrapper.setPropertyValue("attributes[title]", "Manager");
520
wrapper.setPropertyValue("attributes[department]", "Engineering");
521
522
// Type conversion example
523
SimpleTypeConverter converter = new SimpleTypeConverter();
524
Date date = converter.convertIfNecessary("2023-01-15", Date.class);
525
List<String> list = converter.convertIfNecessary("a,b,c", List.class);
526
```
527
528
### Property Editor Support
529
530
Registry and support for PropertyEditor instances used in type conversion.
531
532
```java { .api }
533
/**
534
* Interface for strategies that register custom property editors with a property editor registry.
535
*/
536
interface PropertyEditorRegistrar {
537
/**
538
* Register custom PropertyEditors with the given PropertyEditorRegistry.
539
* @param registry the PropertyEditorRegistry to register the custom PropertyEditors with
540
*/
541
void registerCustomEditors(PropertyEditorRegistry registry);
542
}
543
544
/**
545
* Encapsulates methods for registering JavaBeans PropertyEditors.
546
*/
547
interface PropertyEditorRegistry {
548
/**
549
* Register the given custom property editor for all properties of the given type.
550
* @param requiredType the type of the property
551
* @param propertyEditor the editor to register
552
*/
553
void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor);
554
555
/**
556
* Register the given custom property editor for the given type and property, or for all properties of the given type.
557
* @param requiredType the type of the property (can be null if a property is given but should be specified in any case for consistency checking)
558
* @param propertyPath the path of the property (name or nested path), or null if registering an editor for all properties of the given type
559
* @param propertyEditor the editor to register
560
*/
561
void registerCustomEditor(Class<?> requiredType, String propertyPath, PropertyEditor propertyEditor);
562
563
/**
564
* Find a custom property editor for the given type and property.
565
* @param requiredType the type of the property (can be null if a property is given but should be specified in any case for consistency checking)
566
* @param propertyPath the path of the property (name or nested path), or null if looking for an editor for all properties of the given type
567
* @return the registered editor, or null if none
568
*/
569
PropertyEditor findCustomEditor(Class<?> requiredType, String propertyPath);
570
}
571
```
572
573
### Property Editors Collection
574
575
Comprehensive collection of built-in PropertyEditor implementations for converting between string representations and Java objects.
576
577
```java { .api }
578
/**
579
* Property editor for Boolean/boolean properties.
580
*/
581
class CustomBooleanEditor extends PropertyEditorSupport {
582
public CustomBooleanEditor(boolean allowEmpty);
583
public CustomBooleanEditor(String trueString, String falseString, boolean allowEmpty);
584
}
585
586
/**
587
* Property editor for any Number subclass such as Short, Integer, Long, BigInteger, Float, Double, BigDecimal.
588
*/
589
class CustomNumberEditor extends PropertyEditorSupport {
590
public CustomNumberEditor(Class<? extends Number> numberClass, boolean allowEmpty) throws IllegalArgumentException;
591
public CustomNumberEditor(Class<? extends Number> numberClass, NumberFormat numberFormat, boolean allowEmpty) throws IllegalArgumentException;
592
}
593
594
/**
595
* Property editor for Date properties.
596
*/
597
class CustomDateEditor extends PropertyEditorSupport {
598
public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty);
599
public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty, int exactDateLength);
600
}
601
602
/**
603
* Property editor for Character properties.
604
*/
605
class CharacterEditor extends PropertyEditorSupport {
606
public CharacterEditor(boolean allowEmpty);
607
}
608
609
/**
610
* Property editor for Collections, converting any source Collection to a given target Collection type.
611
*/
612
class CustomCollectionEditor extends PropertyEditorSupport {
613
public CustomCollectionEditor(Class<? extends Collection> collectionType);
614
public CustomCollectionEditor(Class<? extends Collection> collectionType, boolean nullAsEmptyCollection);
615
}
616
617
/**
618
* Property editor for Maps, converting any source Map to a given target Map type.
619
*/
620
class CustomMapEditor extends PropertyEditorSupport {
621
public CustomMapEditor(Class<? extends Map> mapType);
622
public CustomMapEditor(Class<? extends Map> mapType, boolean nullAsEmptyMap);
623
}
624
625
/**
626
* Editor for String arrays.
627
*/
628
class StringArrayPropertyEditor extends PropertyEditorSupport {
629
public static final String DEFAULT_SEPARATOR = ",";
630
631
public StringArrayPropertyEditor();
632
public StringArrayPropertyEditor(String separator);
633
public StringArrayPropertyEditor(String separator, String charsToDelete);
634
public StringArrayPropertyEditor(String separator, String charsToDelete, boolean emptyArrayAsNull);
635
public StringArrayPropertyEditor(String separator, String charsToDelete, boolean emptyArrayAsNull, boolean trimValues);
636
}
637
638
/**
639
* Property editor for java.io.File descriptors.
640
*/
641
class FileEditor extends PropertyEditorSupport {
642
public FileEditor();
643
public FileEditor(ResourceEditor resourceEditor);
644
}
645
646
/**
647
* Editor for java.io.InputStream, converting from a Spring resource location String.
648
*/
649
class InputStreamEditor extends PropertyEditorSupport {
650
public InputStreamEditor();
651
public InputStreamEditor(ResourceEditor resourceEditor);
652
}
653
654
/**
655
* Editor for java.io.Reader, converting from a Spring resource location String.
656
*/
657
class ReaderEditor extends PropertyEditorSupport {
658
public ReaderEditor();
659
public ReaderEditor(ResourceEditor resourceEditor);
660
}
661
662
/**
663
* Editor for java.net.URL, converting from a Spring resource location String.
664
*/
665
class URLEditor extends PropertyEditorSupport {
666
public URLEditor();
667
public URLEditor(ResourceEditor resourceEditor);
668
}
669
670
/**
671
* Editor for java.net.URI, converting from a Spring resource location String.
672
*/
673
class URIEditor extends PropertyEditorSupport {
674
public URIEditor();
675
public URIEditor(ClassLoader classLoader);
676
public URIEditor(ClassLoader classLoader, boolean encode);
677
}
678
679
/**
680
* Editor for java.nio.file.Path, converting from a Spring resource location String.
681
*/
682
class PathEditor extends PropertyEditorSupport {
683
public PathEditor();
684
public PathEditor(ResourceEditor resourceEditor);
685
}
686
687
/**
688
* Editor for java.util.Locale, converting from a String representation to a Locale object.
689
*/
690
class LocaleEditor extends PropertyEditorSupport {
691
public LocaleEditor();
692
}
693
694
/**
695
* Editor for java.util.TimeZone, converting from a String representation to a TimeZone object.
696
*/
697
class TimeZoneEditor extends PropertyEditorSupport {
698
public TimeZoneEditor();
699
}
700
701
/**
702
* Editor for java.time.ZoneId, converting from a String representation to a ZoneId object.
703
*/
704
class ZoneIdEditor extends PropertyEditorSupport {
705
public ZoneIdEditor();
706
}
707
708
/**
709
* Editor for java.util.regex.Pattern, converting from a String representation to a Pattern object.
710
*/
711
class PatternEditor extends PropertyEditorSupport {
712
public PatternEditor();
713
public PatternEditor(int flags);
714
}
715
716
/**
717
* Editor for java.nio.charset.Charset, converting from a String representation to a Charset object.
718
*/
719
class CharsetEditor extends PropertyEditorSupport {
720
public CharsetEditor();
721
}
722
723
/**
724
* Editor for java.lang.Class, converting from a String representation to a Class object.
725
*/
726
class ClassEditor extends PropertyEditorSupport {
727
public ClassEditor();
728
public ClassEditor(ClassLoader classLoader);
729
}
730
731
/**
732
* Property editor for an array of Classes, converting from a comma-delimited String to a Class array.
733
*/
734
class ClassArrayEditor extends PropertyEditorSupport {
735
public ClassArrayEditor();
736
public ClassArrayEditor(ClassLoader classLoader);
737
}
738
739
/**
740
* Editor for java.util.UUID, converting from a String representation to a UUID object.
741
*/
742
class UUIDEditor extends PropertyEditorSupport {
743
public UUIDEditor();
744
}
745
746
/**
747
* Editor for java.util.Currency, converting from a String representation to a Currency object.
748
*/
749
class CurrencyEditor extends PropertyEditorSupport {
750
public CurrencyEditor();
751
}
752
```
753
754
### Utility Classes for Property Access
755
756
Utility classes that provide helper methods for property access operations.
757
758
```java { .api }
759
/**
760
* Static convenience methods for JavaBeans.
761
*/
762
class BeanUtils {
763
/**
764
* Instantiate a class using its 'no-arg' constructor.
765
* @param clazz the class to instantiate
766
* @return the new instance
767
* @throws BeanInstantiationException if the bean cannot be instantiated
768
*/
769
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException;
770
771
/**
772
* Instantiate a class using the given constructor.
773
* @param ctor the constructor to use
774
* @param args the constructor arguments to apply
775
* @return the new instance
776
* @throws BeanInstantiationException if the bean cannot be instantiated
777
*/
778
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException;
779
780
/**
781
* Find a method with the given method name and parameter types.
782
* @param clazz the class to introspect
783
* @param methodName the name of the method
784
* @param paramTypes the parameter types of the method
785
* @return the Method object, or null if none found
786
*/
787
public static Method findMethod(Class<?> clazz, String methodName, Class<?>... paramTypes);
788
789
/**
790
* Find a method with the given method name and minimal parameters.
791
* @param clazz the class to introspect
792
* @param methodName the name of the method
793
* @return the Method object, or null if none found
794
*/
795
public static Method findMethodWithMinimalParameters(Class<?> clazz, String methodName) throws IllegalArgumentException;
796
797
/**
798
* Find a method with the given method name and minimal parameters.
799
* @param methods the candidate methods
800
* @param methodName the name of the method
801
* @return the Method object, or null if none found
802
*/
803
public static Method findMethodWithMinimalParameters(Method[] methods, String methodName) throws IllegalArgumentException;
804
805
/**
806
* Find a method with the given method name and the given parameter types.
807
* @param clazz the class to introspect
808
* @param methodName the name of the method
809
* @param paramTypes the parameter types of the method
810
* @return the Method object, or null if none found
811
*/
812
public static Method resolveSignature(String signature, Class<?> clazz);
813
814
/**
815
* Retrieve the JavaBeans PropertyDescriptors of a given class.
816
* @param clazz the Class to retrieve the PropertyDescriptors for
817
* @return an array of PropertyDescriptors for the given class
818
* @throws BeansException if an error occurs
819
*/
820
public static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws BeansException;
821
822
/**
823
* Retrieve the JavaBeans PropertyDescriptor for the given property.
824
* @param clazz the Class to retrieve the PropertyDescriptor for
825
* @param propertyName the name of the property
826
* @return the PropertyDescriptor for the given property
827
* @throws BeansException if an error occurs
828
*/
829
public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) throws BeansException;
830
831
/**
832
* Find a JavaBeans PropertyDescriptor for the given method.
833
* @param method the method to find a corresponding PropertyDescriptor for
834
* @return the corresponding PropertyDescriptor, or null if none
835
* @throws BeansException if an error occurs
836
*/
837
public static PropertyDescriptor findPropertyForMethod(Method method) throws BeansException;
838
839
/**
840
* Find a JavaBeans PropertyDescriptor for the given method.
841
* @param method the method to find a corresponding PropertyDescriptor for
842
* @param clazz the (most specific) class to introspect for descriptors
843
* @return the corresponding PropertyDescriptor, or null if none
844
* @throws BeansException if an error occurs
845
*/
846
public static PropertyDescriptor findPropertyForMethod(Method method, Class<?> clazz) throws BeansException;
847
848
/**
849
* Find a JavaBeans setter method for the given property.
850
* @param clazz the Class to find the method on
851
* @param propertyName the property name
852
* @return the setter method, or null if none
853
*/
854
public static Method findPropertyType(String propertyName, Class<?>... beanClasses);
855
856
/**
857
* Obtain a new MethodParameter object for the write method of the specified property.
858
* @param pd the PropertyDescriptor for the property
859
* @return a corresponding MethodParameter object
860
*/
861
public static MethodParameter getWriteMethodParameter(PropertyDescriptor pd);
862
863
/**
864
* Check if the given type represents a "simple" property.
865
* @param type the type to check
866
* @return whether the given type represents a "simple" property
867
*/
868
public static boolean isSimpleProperty(Class<?> type);
869
870
/**
871
* Check if the given type represents a "simple" value type.
872
* @param type the type to check
873
* @return whether the given type represents a "simple" value type
874
*/
875
public static boolean isSimpleValueType(Class<?> type);
876
877
/**
878
* Copy the property values of the given source bean into the target bean.
879
* @param source the source bean
880
* @param target the target bean
881
* @throws BeansException if the copying failed
882
*/
883
public static void copyProperties(Object source, Object target) throws BeansException;
884
885
/**
886
* Copy the property values of the given source bean into the given target bean.
887
* @param source the source bean
888
* @param target the target bean
889
* @param editable the class (or interface) to restrict property setting to
890
* @throws BeansException if the copying failed
891
*/
892
public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansException;
893
894
/**
895
* Copy the property values of the given source bean into the given target bean.
896
* @param source the source bean
897
* @param target the target bean
898
* @param ignoreProperties array of property names to ignore
899
* @throws BeansException if the copying failed
900
*/
901
public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException;
902
}
903
904
/**
905
* Utility methods for property access, particularly for bean property paths.
906
*/
907
class PropertyAccessorUtils {
908
/**
909
* Determine whether the given registered path matches the given property path.
910
* @param registeredPath the registered path
911
* @param propertyPath the property path to check
912
* @return whether the paths match
913
*/
914
public static boolean matchesProperty(String registeredPath, String propertyPath);
915
916
/**
917
* Determine the canonical name for the given property path.
918
* @param propertyPath the original property path
919
* @return the canonical property path
920
*/
921
public static String canonicalPropertyName(String propertyPath);
922
923
/**
924
* Determine all canonical names for the given property paths.
925
* @param propertyNames the original property names
926
* @return the canonical property names array
927
*/
928
public static String[] canonicalPropertyNames(String[] propertyNames);
929
930
/**
931
* Return the actual property name for the given property path.
932
* @param propertyPath the property path to check
933
* @return the actual property name, or null if none
934
*/
935
public static String getPropertyName(String propertyPath);
936
937
/**
938
* Check whether the given property path indicates an indexed or nested property.
939
* @param propertyPath property path to check
940
* @return whether the path indicates an indexed or nested property
941
*/
942
public static boolean isNestedOrIndexedProperty(String propertyPath);
943
944
/**
945
* Determine the first nested property separator in the given property path.
946
* @param propertyPath the property path to check
947
* @return the index of the nested property separator, or -1 if none
948
*/
949
public static int getFirstNestedPropertySeparatorIndex(String propertyPath);
950
951
/**
952
* Determine the first nested property separator in the given property path.
953
* @param propertyPath the property path to check
954
* @return the index of the nested property separator, or -1 if none
955
*/
956
public static int getLastNestedPropertySeparatorIndex(String propertyPath);
957
}
958
959
/**
960
* Utility class for working with property descriptors.
961
*/
962
class PropertyDescriptorUtils {
963
/**
964
* See PropertyDescriptor.hashCode().
965
* @param pd the PropertyDescriptor
966
* @return the hash code
967
*/
968
public static int hashCode(PropertyDescriptor pd);
969
970
/**
971
* See PropertyDescriptor.equals(Object).
972
* @param pd the PropertyDescriptor
973
* @param otherPd the other PropertyDescriptor
974
* @return whether they are equal
975
*/
976
public static boolean equals(PropertyDescriptor pd, PropertyDescriptor otherPd);
977
}
978
```
979
980
### Type Conversion Support
981
982
Additional classes and interfaces for advanced type conversion.
983
984
```java { .api }
985
/**
986
* Interface for type conversion between Object instances.
987
*/
988
interface TypeConverter {
989
/**
990
* Convert the value to the required type (may be an array or collection).
991
* @param value the value to convert (may be null)
992
* @param requiredType the type we must convert to (must not be null)
993
* @return the new value, possibly the result of type conversion
994
* @throws TypeMismatchException if type conversion failed
995
*/
996
<T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException;
997
998
/**
999
* Convert the value to the required type.
1000
* @param value the value to convert (may be null)
1001
* @param requiredType the type we must convert to (must not be null)
1002
* @param methodParam the method parameter that is the target of the conversion
1003
* @return the new value, possibly the result of type conversion
1004
* @throws TypeMismatchException if type conversion failed
1005
*/
1006
<T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException;
1007
1008
/**
1009
* Convert the value to the required type.
1010
* @param value the value to convert (may be null)
1011
* @param requiredType the type we must convert to (must not be null)
1012
* @param field the reflective field that is the target of the conversion
1013
* @return the new value, possibly the result of type conversion
1014
* @throws TypeMismatchException if type conversion failed
1015
*/
1016
<T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException;
1017
1018
/**
1019
* Convert the value to the required type.
1020
* @param value the value to convert (may be null)
1021
* @param requiredType the type we must convert to (must not be null)
1022
* @param typeDescriptor the type descriptor to use (may be null)
1023
* @return the new value, possibly the result of type conversion
1024
* @throws TypeMismatchException if type conversion failed
1025
*/
1026
default <T> T convertIfNecessary(Object value, Class<T> requiredType, TypeDescriptor typeDescriptor) throws TypeMismatchException {
1027
throw new UnsupportedOperationException("TypeDescriptor resolution not supported");
1028
}
1029
}
1030
1031
/**
1032
* Simple implementation of the TypeConverter interface that does not operate on a specific target object.
1033
*/
1034
class SimpleTypeConverter extends PropertyEditorRegistrySupport implements TypeConverter {
1035
/**
1036
* Create a new SimpleTypeConverter.
1037
*/
1038
public SimpleTypeConverter();
1039
1040
/**
1041
* Set a ConversionService to use as fallback.
1042
* @param conversionService the ConversionService to use as fallback
1043
*/
1044
public void setConversionService(ConversionService conversionService);
1045
1046
/**
1047
* Return the ConversionService used as fallback.
1048
* @return the ConversionService used as fallback, or null if none
1049
*/
1050
public ConversionService getConversionService();
1051
}
1052
```
1053