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