BeanWrapper
Typically a Bean contains a default no-argument constructor, and get and set methods for attributes.
Org. Springframework. Beans inside the package there is a very important class called BeanWrapper interface and the realization of his BeanWrapperImpl, BeanWrapper offers set and get attributes values (a single or batch), obtain the function of the descriptors and query attribute, To determine whether they are readable or writable.
In addition, BeanWrapper supports nested properties, allowing the properties of child properties to be set to infinite depth. BeanWrapper also supports the addition of standard JavaBeans properties PropertyChangeListeners and VetoableChangeListeners without the need to support the code in the target class. Finally, BeanWrapper provides support for setting index properties. BeanWrapper is usually not used directly by application code, but by DataBinder and BeanFactory.
BeanWrapper provides setPropertyValue, setPropertyValues, getPropertyValue and getPropertyValues methods, as well as a series of overridden methods to operate on beans.
Here is an example of using BeanWrapper. Let’s define two beans:
@Data
public class Company {
private String name;
private Employee managingDirector;
}
Copy the code
@Data
public class Employee {
private String name;
private float salary;
}
Copy the code
Here’s an example:
public class BeanWrapperUsage {
public static void main(String[] args) {
BeanWrapper company = new BeanWrapperImpl(new Company());
// setting the company name..
company.setPropertyValue("name"."Some Company Inc.");
// ... can also be done like this:
PropertyValue value = new PropertyValue("name"."Some Company Inc.");
company.setPropertyValue(value);
// ok, let's create the director and tie it to the company:
BeanWrapper jim = new BeanWrapperImpl(new Employee());
jim.setPropertyValue("name"."Jim Stravinsky");
company.setPropertyValue("managingDirector", jim.getWrappedInstance());
// retrieving the salary of the managingDirector through the company
Float salary = (Float) company.getPropertyValue("managingDirector.salary"); }}Copy the code
Note the use of setPropertyValue and getPropertyValue.
The propertyName property can be in the following forms:
Expression | Explanation |
---|---|
name | Indicates property name relative to getName(), isName(), and setName(..) methods |
account.name | Indicates the name property inside the Account, corresponding to the getAccount().setName() and getAccount().getName() methods. |
account[2] | Indicating the third element of the account, the index attribute can be array, list, or any other naturally ordered collection. |
account[COMPANYNAME] | A map with COMPANYNAMEs as the key |
PropertyEditor
Spring uses the concept of PropertyEditor to convert objects and strings.
For example, you configure a time object, but on configuration, you might need to pass in a String, which can then be automatically converted to the time type via PropertyEditor.
There are several ways to use PropertyEditor in Spring:
-
The properties of the bean are set using the PropertyEditor implementation. When a String is used as an attribute value for a bean declared in an XML file, Spring (if the setter for the corresponding attribute has Class parameters) uses the ClassEditor to try to resolve the parameters into a Class object.
-
Parsing HTTP request parameters in Spring’s MVC framework is done using various property editor implementations that can be manually bound to all subclasses of CommandController.
Spring has a built-in convenience PropertyEditor implementation, they’re all org. Springframework. Beans. Propertyeditors bag inside, most of whom were registered by BeanWrapperImpl. The following table lists the various PropertyEditor that Spring provides:
Class | Explanation |
---|---|
ByteArrayPropertyEditor | Byte array editor. Converts a string to the corresponding byte representation. BeanWrapperImpl is registered by default. |
ClassEditor | Parse a string representing a class into an actual class and vice versa. IllegalArgumentException is raised when the class cannot be found. By default, BeanWrapperImpl is registered. |
CustomBooleanEditor | Customizable property editor for Boolean properties. By default, it is registered by BeanWrapperImpl, but can be overridden by registering its custom instance as a custom editor. |
CustomCollectionEditor | A property editor for collections that converts any source collection to the given target collection type. |
CustomDateEditor | Date customizable property editor for java.util.date that supports custom date formats. Not registered by default. User registration must be done in the appropriate format as required. |
CustomNumberEditor | Customizable property editor for any numeric subclass, such as INTEGER, Long, float, or double. By default, it is registered by BeanWrapperImpl, but can be overridden by registering its custom instance as a custom editor. |
FileEditor | Parse String into a java.io.File object. The default registration is BeanWrapperImpl. |
InputStreamEditor | A one-way property editor that takes a string and generates an InputStream (through the intermediate ResourceEditor and Resource) so that the InputStream property can be set directly to a string. Note that the default usage does not turn off inputStream for you. By default, BeanWrapperImpl is registered. |
LocaleEditor | Strings can be parsed as locale objects and vice versa (the string format is [country][variant], the same as the toString () method for locale). By default, BeanWrapperImpl is registered. |
PatternEditor | Strings can be parsed into java.util.regex.pattern objects and vice versa. |
PropertiesEditor | Strings (formatted using the format defined in Javadoc of the java.util.properties class) can be converted into property objects. By default, BeanWrapperImpl is registered. |
StringTrimmerEditor | Trim the property editor for strings. (Optional) Allows an empty string to be converted to a null value. Unregistered by default – must be user registered. |
URLEditor | You can parse the string representation of a URL into an actual URL object. By default, BeanWrapperImpl is registered. |
Spring using Java. Beans. PropertyEditorManager as property Editor might need to set the search path, if the standard JavaBeans infrastructure and dispose of them in the same package, the class and have the same name, and attached the Editor, Then the standard JavaBeans infrastructure automatically discovers the PropertyEditor class (no explicit registration required). For example, you can have the following class and package structures that are sufficient for the SomethingEditor class to be recognized and used as a property editor for a typed property.
The directory structure is as follows:
com
flydean
beans
ExoticType
ExoticTypeEditor
Copy the code
Here are the definitions for ExoticType and ExoticTypeEditor:
@Data
public class ExoticType {
private String name;
public ExoticType(String name) {
this.name = name; }}Copy the code
public class ExoticTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
setValue(newExoticType(text.toUpperCase())); }}Copy the code
In addition to automatic registration, you can also use CustomEditorConfigurer to register the newly created PropertyEditor with ApplicationContext:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.flydean.beans.ExoticType" value="com.flydean.beans.ExoticTypeEditor"/>
</map>
</property>
</bean>
Copy the code
You can also use the standard BeanInfo JavaBeans mechanism. The following example uses the BeanInfo mechanism to explicitly register one or more PropertyEditor instances with properties of the associated class:
com
flydean
beans
ExoticType
ExoticTypeBeanInfo
Copy the code
The Java source code for the ExoticTypeBeanInfo class referenced below associates the CustomNumberEditor with the Age attribute of the ExoticType class:
public class ExoticTypeBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true);
PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", ExoticType.class) {
public PropertyEditor createPropertyEditor(Object bean) {
return numberPE;
};
};
return new PropertyDescriptor[] { ageDescriptor };
}
catch (IntrospectionException ex) {
throw newError(ex.toString()); }}}Copy the code
PropertyEditorRegistrar
Another mechanism to register the property editor into the Spring container is to use PropertyEditorRegistrar.
Here’s an example:
public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
// it is expected that new PropertyEditor instances are created
registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());
// you could register as many custom property editors as are required here...}}Copy the code
Here is a configuration example using CustomEditorConfigurer:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<ref bean="customPropertyEditorRegistrar"/>
</list>
</property>
</bean>
<bean id="customPropertyEditorRegistrar"
class="com.flydean.beans.CustomPropertyEditorRegistrar"/>
Copy the code
See beanWrapper-propertyeditor for examples in this section
See flydean’s blog for more tutorials